00001
00095 #include "ctl/ctldef.h"
00096 #include "ctl/mstime.h"
00097
00098 #ifndef OPC_H
00099 #include "opc.h"
00100 #endif
00101
00102 #ifndef GUI_H
00103 #include "gui.h"
00104 #endif
00105
00106 #if ( !defined(GUI_SELECT) || !defined(GUI_GetKeyPress) || !defined(GUI_ClearKeyPress) )
00107 #error The GUI_GetKeyPress macro and GUI_SELECT must be defined for GUI to know how to tab and select.
00108 #endif
00109
00110 #if !defined(GUI_GetPointer) && !defined(GUI_TABLEFT) && !defined(GUI_TABRIGHT) && !defined(GUI_TABUP) && !defined(GUI_TABDOWN) && !defined(GUI_TAB) && !defined(GUI_TABBACK)
00111 #error Without a pointer, tabbing must be defined for GUI_getkeybits. As a minimum, one tab and one select.
00112 #endif
00113
00114 #if !defined(GUI_PICK)
00115 #define GUI_PICK GUI_SELECT
00116 #endif
00117
00118 #if !defined(GUI_MSTime)
00119 #error No realtime function defined
00120 #endif
00121
00122 #if !defined(GUI_RepeatPause)
00123 #define GUI_RepeatPause(rate) 132
00124 #endif
00125
00126 #if !defined(GUI_DefaultRepeat)
00127 #define GUI_DefaultRepeat 66
00128 #endif
00129
00130 #ifndef GUI_Tabsound
00131 #define GUI_Tabsound()
00132 #endif
00133
00134 #ifndef GUI_SelectSound
00135 #define GUI_SelectSound()
00136 #endif
00137
00138 #ifndef GUI_CheckSound
00139 #define GUI_CheckSound()
00140 #endif
00141
00142 #ifndef GUI_UncheckSound
00143 #define GUI_UncheckSound()
00144 #endif
00145
00146 #ifndef GUI_ScrollSound
00147 #define GUI_ScrollSound()
00148 #endif
00149
00150 #ifndef GUI_Font
00151 #define GUI_Font( font ) (font)
00152 #endif
00153
00154 #ifndef GUI_Random
00155 #include <stdlib.h>
00156 #define GUI_Random() rand()
00157 #define GUI_RAND_MAX RAND_MAX
00158 #endif
00159
00160 #ifndef GUI_DrawText
00161 #define GUI_ONELINE 0
00162 #define GUI_LEFT 0
00163 #define GUI_CENTER 1
00164 #define GUI_RIGHT 2
00165 #define GUI_TOP 0
00166 #define GUI_VCENTER 4
00167 #define GUI_BOTTOM 8
00177 #define GUI_DrawText( opc, prcBounds, flags, sz, count )
00178
00186 #define GUI_MeasureText( prcBounds, flags, sz, count )
00187
00188 #elif !defined(GUI_MeasureText)
00189 #error GUI_MeasureText is required if you define GUI_DrawText
00190 #endif
00191
00197 bool GUI_tableft( GUI* gui )
00198 {
00199 int tabPrev = gui->focus < 0 ? 0 : gui->focus;
00200 bool bWrap = false;
00201 unsigned mask;
00202 int tab = -1;
00203 const GUI_Control* control = GUI_Control_Get( gui, tabPrev );
00204
00205 pointer_foreach_const(GUI_Control* const,gui->htab,gui->cControl, curr )
00206 {
00207 if( *curr == control )
00208 {
00209 tab = tabPrev = (int)(curr - gui->htab);
00210 break;
00211 }
00212 }
00213
00214 assert( tab != -1 );
00215
00216 do
00217 {
00218 if( --tab < 0 )
00219 {
00220 tab = gui->cControl-1;
00221 bWrap = true;
00222 }
00223 control = gui->htab[tab];
00224 mask = GUI_Control_Mask( gui, control );
00225 if( !(mask & (GUICS_INVISIBLE|GUICS_NOFOCUS)) )
00226 break;
00227 }
00228 while( tab != tabPrev );
00229
00230 if( tab != tabPrev )
00231 _GUI_SetFocus( gui, (int)(control-gui->list) );
00232 return bWrap;
00233 }
00234
00240 bool GUI_tabright( GUI* gui )
00241 {
00242 int tabPrev = gui->focus < 0 ? 0 : gui->focus;
00243 bool bWrap = false;
00244 unsigned mask;
00245 int tab = -1;
00246 const GUI_Control* control = GUI_Control_Get( gui, tabPrev );
00247
00248 pointer_foreach_const(GUI_Control* const,gui->htab,gui->cControl, curr )
00249 {
00250 if( *curr == control )
00251 {
00252 tab = tabPrev = (int)(curr - gui->htab);
00253 break;
00254 }
00255 }
00256
00257 assert( tab != -1 );
00258
00259 do
00260 {
00261 if( ++tab >= gui->cControl )
00262 {
00263 tab = 0;
00264 bWrap = true;
00265 }
00266 control = gui->htab[tab];
00267 mask = GUI_Control_Mask( gui, control );
00268 if( !(mask & (GUICS_INVISIBLE|GUICS_NOFOCUS)) )
00269 break;
00270 }
00271 while( tab != tabPrev );
00272
00273 if( tab != tabPrev )
00274 _GUI_SetFocus( gui, (int)(control-gui->list) );
00275 return bWrap;
00276 }
00277
00283 bool GUI_tabup( GUI* gui )
00284 {
00285 int tabPrev = gui->focus < 0 ? 0 : gui->focus;
00286 bool bWrap = false;
00287 unsigned mask;
00288 int tab = -1;
00289 const GUI_Control* control = GUI_Control_Get( gui, tabPrev );
00290
00291 pointer_foreach_const(GUI_Control* const,gui->vtab,gui->cControl, curr )
00292 {
00293 if( *curr == control )
00294 {
00295 tab = tabPrev = (int)(curr - gui->vtab);
00296 break;
00297 }
00298 }
00299
00300 assert( tab != -1 );
00301
00302 do
00303 {
00304 if( --tab < 0 )
00305 {
00306 tab = gui->cControl-1;
00307 bWrap = true;
00308 }
00309 control = gui->vtab[tab];
00310 mask = GUI_Control_Mask( gui, control );
00311 if( !(mask & (GUICS_INVISIBLE|GUICS_NOFOCUS)) )
00312 break;
00313 }
00314 while( tab != tabPrev );
00315
00316 if( tab != tabPrev )
00317 _GUI_SetFocus( gui, (int)(control-gui->list) );
00318 return bWrap;
00319 }
00320
00326 bool GUI_tabdown( GUI* gui )
00327 {
00328 int tabPrev = gui->focus < 0 ? 0 : gui->focus;
00329 bool bWrap = false;
00330 unsigned mask;
00331 int tab = -1;
00332 const GUI_Control* control = GUI_Control_Get( gui, tabPrev );
00333
00334 pointer_foreach_const(GUI_Control* const,gui->vtab,gui->cControl, curr )
00335 {
00336 if( *curr == control )
00337 {
00338 tab = tabPrev = (int)(curr - gui->vtab);
00339 break;
00340 }
00341 }
00342
00343 assert( tab != -1 );
00344
00345 do
00346 {
00347 if( ++tab >= gui->cControl )
00348 {
00349 tab = 0;
00350 bWrap = true;
00351 }
00352 control = gui->vtab[tab];
00353 mask = GUI_Control_Mask( gui, control );
00354 if( !(mask & (GUICS_INVISIBLE|GUICS_NOFOCUS)) )
00355 break;
00356 }
00357 while( tab != tabPrev );
00358
00359 if( tab != tabPrev )
00360 _GUI_SetFocus( gui, (int)(control-gui->list) );
00361 return bWrap;
00362 }
00363
00364 #if ( defined(GUI_TABLEFT) || defined(GUI_TABRIGHT) || defined(GUI_TABUP) || defined(GUI_TABDOWN) || defined(GUI_TAB) || defined(GUI_TABBACK) )
00365
00370 bool GUI_tabhandler( struct GUI* gui )
00371 {
00372 unsigned keypress = GUI_GetKeyPress();
00373 int prev = gui->focus;
00374 if( !keypress )
00375 return false;
00376 #if defined(GUI_TABLEFT)
00377 else if( keypress == GUI_TABLEFT
00378 #if defined(GUI_TABBACK)
00379 || keypress == GUI_TABBACK
00380 #endif
00381 )
00382 {
00383
00384 if( GUI_tableft( gui ) && gui->parent && !GUI_tableft( gui->parent ) )
00385 {
00386 gui->focus = -1;
00387 }
00388 else
00389 {
00390 GUI_ClearKeyPress();
00391 }
00392 }
00393 #endif
00394 #if defined(GUI_TABRIGHT)
00395 else if( keypress == GUI_TABRIGHT
00396 #if defined(GUI_TAB)
00397 || keypress == GUI_TAB
00398 #endif
00399 )
00400 {
00401 if( GUI_tabright( gui ) && gui->parent && !GUI_tabright( gui->parent ) )
00402 {
00403 gui->focus = -1;
00404 }
00405 else
00406 {
00407 GUI_ClearKeyPress();
00408 }
00409 }
00410 #endif
00411 #if defined(GUI_TABUP)
00412 else if( keypress == GUI_TABUP)
00413 {
00414 if( GUI_tabup( gui ) && gui->parent && !GUI_tabup( gui->parent ) )
00415 {
00416 gui->focus = -1;
00417 }
00418 else
00419 {
00420 GUI_ClearKeyPress();
00421 }
00422 }
00423 #endif
00424 #if defined(GUI_TABDOWN)
00425 else if( keypress == GUI_TABDOWN)
00426 {
00427 if( GUI_tabdown( gui ) && gui->parent && !GUI_tabdown( gui->parent ) )
00428 {
00429 gui->focus = -1;
00430 }
00431 else
00432 {
00433 GUI_ClearKeyPress();
00434 }
00435 }
00436 #endif
00437 if( gui->focus != prev )
00438 {
00439 GUI_Tabsound();
00440 return true;
00441 }
00442 return false;
00443 }
00444 #endif
00445
00447 void _GUI_Dirty_Rect( GUI* gui, const Rect* prc )
00448 {
00449 #ifdef SIMPLE_DIRTY
00450 RectUnionRect( gui->dirty, *prc )
00451 #else
00452
00453 assert( gui->cdirty );
00454
00455
00456
00457
00458 assert( !(gui->mask & GUIM_INPAINT) );
00459 ClipRect_add( gui->cdirty, prc );
00460 #endif
00461 }
00462
00470 bool GUI_Control_Paint( const struct GUI* gui, const GUI_Control* control, OPC* opc )
00471 {
00472 GUI_Control_State* state = GUI_Control_Data( gui, control );
00473 if( state->mask & GUICS_INVISIBLE )
00474 {
00475 return false;
00476 }
00477 else
00478 {
00479 Rect bound;
00480 GUI_Control_Bound( gui, control, &bound );
00481
00482 RectIntRect( bound, gui->dirty );
00483 if( RectEmpty( bound ) )
00484 return false;
00485 OPC_NAMING(Clip)( opc, &gui->opc, &bound );
00486 }
00487 return true;
00488 }
00489
00495 bool _GUI_IsOpen( GUI* gui )
00496 {
00497 return gui && (gui->mask & GUIM_ALIVE);
00498 }
00499
00506 int _GUI_SetFocus( GUI* gui, int ifocus )
00507 {
00508 int focusPrev;
00509 assert(gui);
00510 focusPrev = gui->focus;
00511 gui->focus = ifocus;
00512 if( gui->focus >= 0 && gui->focus < gui->cControl )
00513 {
00514 if( GUI_Control_IsFocused( gui, gui->list + gui->focus ) )
00515 {
00516 if( focusPrev != gui->focus )
00517 {
00518 GUI_Control_Dirty( gui, gui->list + gui->focus );
00519 gui->mask |= GUIM_FOCUSCHANGED;
00520 }
00521 }
00522 else
00523 GUI_tabright( gui );
00524 }
00525 if( focusPrev != gui->focus )
00526 {
00527 if( focusPrev >= 0 && focusPrev < gui->cControl )
00528 {
00529 GUI_Control_Dirty( gui, gui->list + focusPrev );
00530 gui->mask |= GUIM_FOCUSCHANGED;
00531 }
00532 }
00533 return focusPrev;
00534 }
00535
00540 void _GUI_CallNotifies( GUI* gui )
00541 {
00542
00543 assert(gui);
00544 for( gui->iControl = 0; gui->iControl < gui->cControl; ++gui->iControl )
00545 {
00546 GUI_Control_State* data = GUI_Control_Get_Data( gui, gui->iControl );
00547 if( data->mask & GUICS_NOTIFY )
00548 {
00549 gui->handler(gui, GUI_Notify);
00550 data->mask &= ~GUICS_NOTIFY;
00551 }
00552 }
00553 }
00554
00559 void _GUI_Heartbeat( GUI* gui )
00560 {
00561
00562
00563
00564
00565
00566
00567
00568
00569 assert(gui);
00570 if( GUI_IsOpen( gui ) )
00571 gui->handler( gui, GUI_Cycle );
00572 if( GUI_IsOpen( gui ) && (gui->mask & GUIM_FOCUSCHANGED) )
00573 {
00574 gui->mask &= ~GUIM_FOCUSCHANGED;
00575 gui->handler( gui, GUI_Focus );
00576 }
00577 if( GUI_IsOpen( gui ) )
00578 {
00579 gui->handler( gui, GUI_Paint );
00580 #ifndef SIMPLE_DIRTY
00581 ClipRect_clear( gui->cdirty );
00582 #endif
00583 _GUI_CallNotifies( gui );
00584 }
00585 }
00586
00587
00588 bool _GUI_Control_IsFocused( const GUI* gui, const GUI_Control* control )
00589 {
00590 return (gui->list + gui->focus) == control && !(GUI_Control_Mask( gui, control ) & (GUICS_INVISIBLE|GUICS_NOFOCUS));
00591 }
00592
00593 bool _GUI_Control_IsHidden( const GUI* gui, int index )
00594 {
00595 return 0 != (GUI_Control_Data( gui, GUI_Control_Get( gui, index ) )->mask & GUICS_INVISIBLE);
00596 }
00597
00598 void _GUI_Control_Hide( GUI* gui, int index )
00599 {
00600 if( !GUI_Control_IsHidden( gui, index ) )
00601 {
00602 if( gui->focus == index )
00603 GUI_tabright( gui );
00604 GUI_Control_Set_Dirty( gui, index );
00605 GUI_Control_Data( gui, GUI_Control_Get( gui, index ) )->mask |= GUICS_INVISIBLE;
00606 }
00607 }
00608
00609 void _GUI_Control_Show( GUI* gui, int index )
00610 {
00611 if( GUI_Control_IsHidden( gui, index ) )
00612 {
00613 GUI_Control_Data( gui, GUI_Control_Get( gui, index ) )->mask &= ~GUICS_INVISIBLE;
00614 GUI_Control_Set_Dirty( gui, index );
00615 if( gui->focus == index )
00616 GUI_tabright( gui );
00617 }
00618 }
00619
00620 bool _GUI_Control_IsDisabled( const GUI* gui, int index )
00621 {
00622 return 0 != (GUI_Control_Data( gui, GUI_Control_Get( gui, index ) )->mask & GUICS_NOFOCUS);
00623 }
00624 void _GUI_Control_Enable( GUI* gui, int index )
00625 {
00626 if( GUI_Control_IsDisabled( gui, index ) )
00627 {
00628 GUI_Control_Data( gui, GUI_Control_Get( gui, index ) )->mask &= ~GUICS_NOFOCUS;
00629 GUI_Control_Set_Dirty( gui, index );
00630 if( gui->focus == index )
00631 GUI_tabright( gui );
00632 }
00633 }
00634 void _GUI_Control_Disable( GUI* gui, int index )
00635 {
00636 if( !GUI_Control_IsDisabled( gui, index ) )
00637 {
00638 if( gui->focus == index )
00639 GUI_tabright( gui );
00640 GUI_Control_Data( gui, GUI_Control_Get( gui, index ) )->mask |= GUICS_NOFOCUS;
00641 GUI_Control_Set_Dirty( gui, index );
00642 }
00643 }
00644
00645
00659 bool _GUI_Explode_Set( GUI* gui, int times, int divide, int first, int last )
00660 {
00661 bool alldone = true;
00662 assertobjptr(gui);
00663 assert( first >= 0 && first < gui->cControl );
00664 assert( last >= first && last < gui->cControl );
00665 {
00666 pointer_foreach_const( GUI_Control, gui->list+first, (1+last-first), control )
00667 {
00668 GUI_Control_State* state = GUI_Control_Data( gui, control );
00669 if( state->offx || state->offy )
00670 {
00671 Rect bound;
00672 GUI_Control_Bound( gui, control, &bound );
00673 if(
00674 (( times > divide ) && !RectOutside(bound,gui->opc.clip)) ||
00675 (( times < divide ) && (state->offx || state->offy) ) )
00676 {
00677 GUI_Control_Dirty( gui, control );
00678 state->offx = (int16)(state->offx * times / divide);
00679 state->offy = (int16)(state->offy * times / divide);
00680 GUI_Control_Dirty( gui, control );
00681 alldone = false;
00682 }
00683 }
00684 }
00685 }
00686 return alldone;
00687 }
00688 bool _GUI_Explode( GUI* gui, int times, int divide )
00689 {
00690 return _GUI_Explode_Set( gui, times, divide, 0, gui->cControl-1 );
00691 }
00692
00704 void _GUI_Sweep_Set( GUI* gui, int x, int y, int times, int divide, int from, int to )
00705 {
00706 assertobjptr(gui);
00707 assert( from >= 0 && from < gui->cControl );
00708 assert( to >= from && to < gui->cControl );
00709 {
00710 pointer_foreach_const( GUI_Control, gui->list + from, 1+to-from, control )
00711 {
00712 _GUI_Offset_Control( gui, control, x, y );
00713 x = x * times / divide;
00714 y = y * times / divide;
00715 }
00716 }
00717 }
00718 void _GUI_Sweep( GUI* gui, int x, int y, int times, int divide )
00719 {
00720 _GUI_Sweep_Set( gui, x,y, times, divide, 0, gui->cControl-1 );
00721 }
00722
00731 void _GUI_Offset_Group( GUI* gui, int from, int to, int x, int y )
00732 {
00733 assert( from >= 0 && from < gui->cControl );
00734 assert( to >= from && to < gui->cControl );
00735 {
00736 pointer_foreach_const( GUI_Control, gui->list + from, 1+to-from, control )
00737 _GUI_Offset_Control( gui, control, x, y );
00738 }
00739 }
00740
00748 void _GUI_Offset_Control( GUI* gui, const GUI_Control* control, int x, int y )
00749 {
00750 GUI_Control_State* state = GUI_Control_Data( gui, control );
00751 GUI_Control_Dirty( gui, control );
00752 state->offx = (int16)x;
00753 state->offy = (int16)y;
00754 GUI_Control_Dirty( gui, control );
00755 }
00756
00763 void _GUI_Control_Set_Offset( GUI* gui, int index, int px, int py )
00764 {
00765 const GUI_Control* control = GUI_Control_Get( gui, index );
00766 GUI_Control_State* state = GUI_Control_Data( gui, control );
00767 GUI_Control_Dirty( gui, control );
00768 state->offx = (int16)px;
00769 state->offy = (int16)py;
00770 GUI_Control_Dirty( gui, control );
00771 }
00772
00779 void _GUI_Move( GUI* gui, int x, int y )
00780 {
00781 if( gui->offx != x || gui->offy != y )
00782 {
00783 gui->offx = x;
00784 gui->offy = y;
00785 GUI_Dirty_Rect( gui, &gui->opc.clip );
00786 }
00787 }
00788
00789
00796 bool _GUI_Motion( GUI* gui, int tx, int ty )
00797 {
00798 if( gui->offx == tx && gui->offy == ty )
00799 return true;
00800 GUI_Dirty( gui );
00801 gui->offx = (tx + gui->offx) / 2;
00802 gui->offy = (ty + gui->offy) / 2;
00803 if( abs(gui->offx - tx) <= 8 && abs(gui->offy - ty) <= 8 )
00804 {
00805 gui->offx = tx;
00806 gui->offy = ty;
00807 }
00808 GUI_Dirty( gui );
00809 return false;
00810 }
00811
00812 #ifndef NDEBUG
00813
00818 const GUI_Control* _GUI_Control_Get( const GUI* gui, int index )
00819 {
00820
00821 assertobjptr(gui);
00822 assert( index >= 0 && index < gui->cControl );
00823 return gui->list + index;
00824 }
00825
00831 GUI_Control_State* _GUI_Control_Data( const GUI* gui, const GUI_Control* control )
00832 {
00833 assertobjptr(gui);
00834 assertobjptr(control);
00835
00836 assert( control->offData >= sizeof(GUI) );
00837 return (GUI_Control_State*)((uint8*)gui + control->offData);
00838 }
00839
00840 #endif
00841
00849 void GUI_Def_State( GUI* gui, const GUI_Control* control, unsigned initmask, unsigned align )
00850 {
00851 GUI_Control_State* state = GUI_Control_Data( gui, control );
00852 state->mask = initmask;
00853 state->offx = state->offy = 0;
00854 state->text = NULL;
00855 state->align = align;
00856 state->frames = control->state;
00857 state->cFrames = control->cState;
00858 }
00859
00867 void _GUI_Control_SetFrames( GUI* gui, int index, const OPCShape* const* frames, size_t cFrames )
00868 {
00869 GUI_Control_State* state = (GUI_Control_State*)GUI_Control_Get_Data( gui, index );
00870 state->frames = frames;
00871 state->cFrames = cFrames;
00872 GUI_Control_Set_Dirty( gui,index );
00873 }
00874
00881 void _GUI_Control_SetText( GUI* gui, int index, const GUI_CHAR* szText)
00882 {
00883 GUI_Control_Get_Data( gui,index )->text = szText;
00884 GUI_Control_Set_Dirty( gui,index );
00885 }
00886
00893 void _GUI_Control_SetJustify( GUI* gui, int index, unsigned just )
00894 {
00895 GUI_Control_Get_Data( gui,index )->align = just;
00896 GUI_Control_Set_Dirty( gui,index );
00897 }
00898
00906 void _GUI_Control_SetupText( GUI* gui, int index, const GUI_CHAR* szText, unsigned just )
00907 {
00908 GUI_Control_State* state = (GUI_Control_State*)GUI_Control_Get_Data( gui, index );
00909 state->text = szText;
00910 state->align = just;
00911 GUI_Control_Set_Dirty( gui, index );
00912 }
00913
00919 void _GUI_Control_Dirty( GUI* gui, const GUI_Control* control )
00920 {
00921 GUI_Control_State* state = GUI_Control_Data( gui, control );
00922 if( !(state->mask & GUICS_INVISIBLE) )
00923 {
00924 Rect bound = (control)->bound;
00925 RectMoveBy(bound,gui->offx+state->offx,gui->offy+state->offy);
00926 GUI_Dirty_Rect( gui, &bound );
00927 }
00928 }
00929
00936 void _GUI_Control_Bound( GUI* gui, const GUI_Control* control, Rect* bound )
00937 {
00938 GUI_Control_State* state = GUI_Control_Data( gui, control );
00939 *bound = (control)->bound;
00940 RectMoveBy(*bound,gui->offx+state->offx,gui->offy+state->offy);
00941 }
00942
00943
00944
00945
00946
00947 #define GUI_Ctrl_ArtResource GUI_Ctrl_Invalid
00948 #define GUI_Ctrl_PaletteData GUI_Ctrl_Invalid
00949 #define GUI_Ctrl_Background GUI_Ctrl_Invalid
00950 #define GUI_Ctrl_Overlay GUI_Ctrl_Invalid
00951
00952
00953 #define XENUM(tag,verbose,data) static void GUI_Ctrl_##verbose( struct GUI* gui, const struct GUI_Control* control, GUI_Message msg );
00954 EDEF_HANDLERS(XENUM)
00955 #undef XENUM
00956 #define XENUM(tag,verbose,data) GUI_Ctrl_##verbose,
00957 static const GUI_Ctrl_handler lutHandlers[] =
00958 {
00959 EDEF_HANDLERS(XENUM)
00960 };
00961 #undef XENUM
00962
00970 void GUI_Control_handle( struct GUI* gui, const GUI_Control* control, GUI_Message msg )
00971 {
00972 assertobjptr(gui);
00973 assertobjptr(control);
00974 {
00975 GUIHandlers index = control->type;
00976 assert( index >= 0 && index < GUIHandlers_COUNT );
00977 lutHandlers[index]( gui, control, msg );
00978 }
00979 }
00980
00984 void GUI_Ctrl_Invalid( struct GUI* gui, const struct GUI_Control* control, GUI_Message msg )
00985 {
00986 }
00987
00991 void GUI_Ctrl_StaticFrame( struct GUI* gui, const struct GUI_Control* control, GUI_Message msg )
00992 {
00993 switch( msg )
00994 {
00995 case GUI_Paint:
00996 {
00997 GUI_Control_State* state = GUI_Control_Data( gui, control );
00998 OPC opc;
00999 if( ((state->frames && state->cFrames) || (state->text && *state->text)) && GUI_Control_Paint( gui, control, &opc ) )
01000 {
01001 Rect bound;
01002 GUI_Control_Bound( gui, control, &bound );
01003 if( state->frames && state->cFrames )
01004 {
01005 OPC_NAMING(Shape)( &opc, *state->frames, bound.left, bound.top );
01006 }
01007 if( state->text && *state->text )
01008 {
01009
01010 GUI_DrawText( &opc, &bound, state->align, state->text, ~0u );
01011 }
01012 }
01013 }
01014 break;
01015 case GUI_Init:
01016 GUI_Def_State(gui,control,GUICS_NOFOCUS,GUI_CENTER|GUI_VCENTER);
01017 return;
01018
01019 default:
01020 break;
01021 }
01022 }
01023
01027 void GUI_Ctrl_Button( struct GUI* gui, const struct GUI_Control* control, GUI_Message msg )
01028 {
01029 switch( msg )
01030 {
01031 case GUI_Cycle:
01032 {
01033
01034 GUI_Button_State* state = (GUI_Button_State*)GUI_Control_Data( gui, control );
01035 if( !state->basic.frames )
01036 {
01037 if( GUI_Control_IsFocused( gui, control ) )
01038 GUI_tabright(gui);
01039 return;
01040 }
01041 if( GUI_Control_IsFocused( gui, control ) )
01042 {
01043 #if ( defined(GUI_TABLEFT) || defined(GUI_TABRIGHT) || defined(GUI_TABUP) || defined(GUI_TABDOWN) )
01044 if( GUI_tabhandler( gui ) )
01045 {
01046 state->tracking = guibs_Neutral;
01047 return;
01048 }
01049 #endif
01050 switch( state->tracking )
01051 {
01052 default:
01053 case guibs_Neutral:
01054
01055 state->tracking = guibs_Focus;
01056 GUI_Control_Dirty( gui, control );
01057
01058 case guibs_Focus:
01059
01060 #if defined(GUI_GetPointer)
01061 if( GUI_GetKeyPress() & GUI_PICK )
01062 {
01063 int x,y;
01064 Rect bound;
01065 GUI_Control_Bound( gui, control, &bound );
01066 GUI_GetPointer(x,y);
01067 if( !RectPtInRect(bound,x,y) )
01068 {
01069 break;
01070 }
01071 }
01072 #endif
01073 #ifdef GUI_GetKeyHeld
01074 if( GUI_GetKeyPress() & (GUI_SELECT|GUI_PICK) )
01075 {
01076 if( state->basic.frames[guibs_Selected] )
01077 {
01078 state->tracking = guibs_Selected;
01079 GUI_ClearKeyPress();
01080 GUI_Control_Dirty( gui, control );
01081 break;
01082 }
01083 #endif
01084 state->tracking = guibs_Focus;
01085 GUI_Control_Dirty( gui, control );
01086 GUI_SelectSound();
01087 GUI_Control_Notify( gui, control );
01088 }
01089 break;
01090
01091 case guibs_Selected:
01092 #ifdef GUI_GetKeyHeld
01093 #if defined(GUI_GetPointer)
01094 if( GUI_GetKeyHeld() == GUI_PICK )
01095 {
01096 int x,y;
01097 Rect bound;
01098 GUI_Control_Bound( gui, control, &bound );
01099 GUI_GetPointer(x,y);
01100 if( !RectPtInRect(bound,x,y) )
01101 {
01102 state->tracking = guibs_Focus;
01103 GUI_Control_Dirty( gui, control );
01104 break;
01105 }
01106 }
01107 #endif
01108 if( (GUI_GetKeyHeld() & (GUI_SELECT|GUI_PICK)) )
01109 break;
01110 #endif
01111 state->tracking = guibs_Focus;
01112 GUI_Control_Dirty( gui, control );
01113 GUI_SelectSound();
01114 GUI_Control_Notify( gui, control );
01115 break;
01116 }
01117 }
01118 else
01119 {
01120 if( state->tracking != guibs_Neutral )
01121 {
01122 state->tracking = guibs_Neutral;
01123 GUI_Control_Dirty( gui, control );
01124 }
01125 }
01126 }
01127 break;
01128 case GUI_Paint:
01129 {
01130 GUI_Button_State* state = (GUI_Button_State*)GUI_Control_Data( gui, control );
01131 OPC opc;
01132 if( state->basic.frames && GUI_Control_Paint( gui, control, &opc ) )
01133 {
01134 Rect bound;
01135 GUI_Control_Bound( gui, control, &bound );
01136
01137 if( GUI_Control_IsFocused( gui, control ) )
01138 OPC_NAMING(Shape)( &opc, state->basic.frames[guibs_FocusUnder], bound.left,bound.top );
01139 switch( state->tracking )
01140 {
01141 default:
01142 case guibs_Focus:
01143 if( state->basic.frames[guibs_Focus] )
01144 OPC_NAMING(Shape)( &opc, state->basic.frames[guibs_Focus], bound.left,bound.top );
01145 else if( state->basic.frames[guibs_Neutral] )
01146 OPC_NAMING(Shape)( &opc, state->basic.frames[guibs_Neutral], bound.left,bound.top );
01147 else
01148 OPC_NAMING(Shape)( &opc, state->basic.frames[guibs_Selected], bound.left,bound.top );
01149 break;
01150 case guibs_Neutral:
01151 OPC_NAMING(Shape)( &opc, state->basic.frames[guibs_Neutral], bound.left,bound.top );
01152 break;
01153 case guibs_Selected:
01154 if( state->basic.frames[guibs_Selected] )
01155 OPC_NAMING(Shape)( &opc, state->basic.frames[guibs_Selected], bound.left,bound.top );
01156 else if( state->basic.frames[guibs_Focus] )
01157 OPC_NAMING(Shape)( &opc, state->basic.frames[guibs_Focus], bound.left,bound.top );
01158 else
01159 OPC_NAMING(Shape)( &opc, state->basic.frames[guibs_Neutral], bound.left,bound.top );
01160 break;
01161 }
01162 if( state->basic.text && *state->basic.text )
01163 {
01164
01165 GUI_DrawText( &opc, &bound, state->basic.align, state->basic.text, ~0u );
01166 }
01167
01168 if( GUI_Control_IsFocused( gui, control ) )
01169 OPC_NAMING(Shape)( &opc, state->basic.frames[guibs_FocusOver], bound.left,bound.top );
01170 }
01171 }
01172 break;
01173 case GUI_Init:
01174 {
01175 GUI_Button_State* state = (GUI_Button_State*)GUI_Control_Data( gui, control );
01176 GUI_Def_State(gui,control,GUICS_DEFAULT,GUI_CENTER|GUI_VCENTER);
01177 state->tracking = guibs_Neutral;
01178 }
01179 break;
01180 default:
01181 break;
01182 }
01183 }
01184
01188 void GUI_Ctrl_Checkbox( struct GUI* gui, const struct GUI_Control* control, GUI_Message msg )
01189 {
01190 switch( msg )
01191 {
01192 case GUI_Cycle:
01193 {
01194
01195 GUI_Checkbox_State* state = (GUI_Checkbox_State*)GUI_Control_Data( gui, control );
01196 if( !state->basic.frames )
01197 {
01198 if( GUI_Control_IsFocused( gui, control ) )
01199 GUI_tabright(gui);
01200 return;
01201 }
01202 if( GUI_Control_IsFocused( gui, control ) )
01203 {
01204 #if ( defined(GUI_TABLEFT) || defined(GUI_TABRIGHT) || defined(GUI_TABUP) || defined(GUI_TABDOWN) )
01205 if( GUI_tabhandler( gui ) )
01206 return;
01207 #endif
01208 if( GUI_GetKeyPress() & (GUI_SELECT|GUI_PICK) )
01209 {
01210 if( state->bCheck )
01211 {
01212 state->bCheck = false;
01213 GUI_UncheckSound();
01214 }
01215 else
01216 {
01217 state->bCheck = true;
01218 GUI_CheckSound();
01219 }
01220 GUI_Control_Notify( gui, control );
01221 GUI_Control_Dirty( gui, control );
01222 GUI_ClearKeyPress();
01223 }
01224 }
01225 }
01226 break;
01227 case GUI_Paint:
01228 {
01229 GUI_Checkbox_State* state = (GUI_Checkbox_State*)GUI_Control_Data( gui, control );
01230 OPC opc;
01231 if( GUI_Control_Paint( gui, control, &opc ) && state->basic.frames )
01232 {
01233 Rect bound;
01234 GUI_Control_Bound( gui, control, &bound );
01235 if( state->basic.text && *state->basic.text )
01236 {
01237
01238 Rect rCheck;
01239 OPC_NAMING(Shape_Bound)( &rCheck, state->basic.frames[state->bCheck ? guics_Checked : guics_Unchecked], bound.left,bound.top );
01240 if( GUI_Control_IsFocused( gui, control ) )
01241 {
01242 Rect rFocus;
01243 OPC_NAMING(Shape_Bound)( &rFocus, state->basic.frames[guics_Focus], bound.left,bound.top );
01244 RectUnionRect( rCheck, rFocus );
01245 }
01246
01247 switch( state->basic.align & (GUI_LEFT|GUI_CENTER|GUI_RIGHT) )
01248 {
01249 default:
01250 case GUI_LEFT:
01251 case GUI_CENTER:
01252 RectLeftTo( rCheck, bound.left );
01253 bound.left = rCheck.right;
01254 break;
01255 case GUI_RIGHT:
01256 RectRightTo( rCheck, bound.right );
01257 bound.right = rCheck.left;
01258 break;
01259 }
01260 switch( state->basic.align & (GUI_TOP|GUI_VCENTER|GUI_BOTTOM) )
01261 {
01262 default:
01263 case GUI_TOP:
01264 case GUI_VCENTER:
01265 RectBottomTo( rCheck, bound.bottom );
01266 bound.bottom = rCheck.top;
01267 break;
01268 case GUI_BOTTOM:
01269 RectTopTo( rCheck, bound.top );
01270 bound.top = rCheck.bottom;
01271 break;
01272 }
01273 GUI_DrawText( &opc, &bound, state->basic.align, state->basic.text, ~0u );
01274 }
01275 else
01276 {
01277 OPC_NAMING(Shape)( &opc, state->basic.frames[state->bCheck ? guics_Checked : guics_Unchecked], bound.left,bound.top );
01278 if( GUI_Control_IsFocused( gui, control ) )
01279 OPC_NAMING(Shape)( &opc, state->basic.frames[guics_Focus], bound.left,bound.top );
01280 }
01281 }
01282 }
01283 break;
01284 case GUI_Init:
01285 {
01286 GUI_Checkbox_State* state = (GUI_Checkbox_State*)GUI_Control_Data( gui, control );
01287 GUI_Def_State(gui,control,GUICS_DEFAULT,GUI_LEFT);
01288 state->bCheck = false;
01289 }
01290 break;
01291 default:
01292 break;
01293 }
01294 }
01295
01303 bool _GUI_Checkbox_SetCheck( GUI* gui, int index, bool bCheck)
01304 {
01305 bool bOld;
01306 const GUI_Control* control = GUI_Control_Get( gui, index );
01307 GUI_Checkbox_State* state = (GUI_Checkbox_State*)GUI_Control_Data( gui, control );
01308 GUI_Assert_Type( gui, index, guih_Checkbox );
01309 bOld = state->bCheck;
01310 state->bCheck = 0 != (bCheck);
01311 if( !(state->basic.mask & (GUICS_INVISIBLE|GUICS_NOFOCUS)) )
01312 state->basic.mask |= GUICS_NOTIFY;
01313 GUI_Control_Dirty( gui, control );
01314 return bOld;
01315 }
01316
01317
01321 void GUI_Ctrl_Animation( struct GUI* gui, const struct GUI_Control* control, GUI_Message msg )
01322 {
01323 switch( msg )
01324 {
01325 case GUI_Cycle:
01326 {
01327 GUI_Animation_State* state = (GUI_Animation_State*)GUI_Control_Data( gui, control );
01328 unsigned mscurr = (unsigned)GUI_MSTime();
01329 if( !state->basic.frames || (state->basic.mask & GUICS_INVISIBLE) )
01330 return;
01331 if( (mscurr-state->msprev) >= state->msframe )
01332 {
01333 switch( state->aDir )
01334 {
01335 case gad_Stop:
01336 default:
01337 return;
01338 case gad_ForwardOneshot:
01339 if( ++state->iFrame >= (int)state->basic.cFrames )
01340 {
01341 state->iFrame = state->basic.cFrames-1;
01342 GUI_Control_Notify( gui, control );
01343 state->aDir = gad_Stop;
01344 }
01345 GUI_Control_Dirty( gui, control );
01346 break;
01347 case gad_BackwardOneshot:
01348 if( --state->iFrame < 0 )
01349 {
01350 state->iFrame = 0;
01351 GUI_Control_Notify( gui, control );
01352 state->aDir = gad_Stop;
01353 }
01354 GUI_Control_Dirty( gui, control );
01355 break;
01356 case gad_ForwardLoop:
01357 if( ++state->iFrame >= (int)state->basic.cFrames )
01358 state->iFrame = 0;
01359 GUI_Control_Dirty( gui, control );
01360 break;
01361 case gad_BackwardLoop:
01362 if( --state->iFrame < 0 )
01363 state->iFrame = (int)state->basic.cFrames-1;
01364 GUI_Control_Dirty( gui, control );
01365 break;
01366 case gad_ForwardPingPong:
01367 if( ++state->iFrame >= (int)state->basic.cFrames-1 )
01368 {
01369 state->iFrame = (int)state->basic.cFrames-1;
01370 state->aDir = gad_BackwardPingPong;
01371 }
01372 GUI_Control_Dirty( gui, control );
01373 break;
01374 case gad_BackwardPingPong:
01375 if( --state->iFrame <= 0 )
01376 {
01377 state->iFrame = 0;
01378 state->aDir = gad_ForwardPingPong;
01379 GUI_Control_Dirty( gui, control );
01380 }
01381 GUI_Control_Dirty( gui, control );
01382 break;
01383 case gad_Random:
01384 {
01385 int nextFrame;
01386 do {
01387 nextFrame = GUI_Random() % state->basic.cFrames;
01388 } while( nextFrame == state->iFrame );
01389 state->iFrame = nextFrame;
01390 GUI_Control_Dirty( gui, control );
01391 }
01392 break;
01393 }
01394 state->msprev = mscurr;
01395 }
01396 }
01397 break;
01398 case GUI_Paint:
01399 {
01400 GUI_Animation_State* state = (GUI_Animation_State*)GUI_Control_Data( gui, control );
01401 OPC opc;
01402 if( state->basic.frames && state->basic.cFrames && GUI_Control_Paint( gui, control, &opc ) )
01403 {
01404 Rect bound;
01405 GUI_Control_Bound( gui, control, &bound );
01406 if( state->iFrame < 0 )
01407 {
01408 state->iFrame = 0;
01409 }
01410 else if( state->iFrame >= (int)state->basic.cFrames )
01411 {
01412 state->iFrame = state->basic.cFrames-1;
01413 }
01414 OPC_NAMING(Shape)( &opc, state->basic.frames[state->iFrame], bound.left,bound.top );
01415 if( state->basic.text && *state->basic.text )
01416 {
01417
01418 GUI_DrawText( &opc, &bound, state->basic.align, state->basic.text, ~0u );
01419 }
01420 }
01421 }
01422 break;
01423 case GUI_Init:
01424 {
01425 GUI_Animation_State* state = (GUI_Animation_State*)GUI_Control_Data( gui, control );
01426 GUI_Def_State(gui,control,GUICS_NOFOCUS,GUI_CENTER|GUI_VCENTER);
01427 state->iFrame = 0;
01428 state->aDir = state->basic.cFrames > 1 ? gad_ForwardLoop : gad_Stop;
01429 state->msframe = 100;
01430 state->msprev = 0;
01431 }
01432 break;
01433 default:
01434 break;
01435 }
01436 }
01437
01444 int _GUI_Animation_SetFrame( GUI* gui, int index, int frame )
01445 {
01446 const GUI_Control* control = GUI_Control_Get( gui, index );
01447 GUI_Animation_State* state = (GUI_Animation_State*)GUI_Control_Data( gui, control );
01448 int frPrev = state->iFrame;
01449 GUI_Assert_Type( gui, index, guih_Animation );
01450 if( state->basic.cFrames > 0 )
01451 state->iFrame = (frame + state->basic.cFrames) % state->basic.cFrames;
01452 else
01453 state->iFrame = 0;
01454 state->aDir = gad_Stop;
01455 if( frPrev != state->iFrame )
01456 GUI_Control_Dirty( gui, control );
01457 return frPrev;
01458 }
01459
01468 void _GUI_Animation_SetAnim( GUI* gui, int index, GUI_AnimDir animdir, int startFrame, unsigned msFrameTime )
01469 {
01470 const GUI_Control* control = GUI_Control_Get( gui, index );
01471 GUI_Animation_State* state = (GUI_Animation_State*)GUI_Control_Data( gui, control );
01472 GUI_Assert_Type( gui, index, guih_Animation );
01473 state->iFrame = max(0,min(startFrame,(int)state->basic.cFrames));
01474 state->msframe = msFrameTime;
01475 state->msprev = (unsigned)GUI_MSTime();
01476 state->aDir = animdir;
01477 GUI_Control_Dirty( gui, control );
01478 }
01479
01480
01486 void GUI_Ctrl_Scrollbar( struct GUI* gui, const struct GUI_Control* control, GUI_Message msg )
01487 {
01488 GUI_Scrollbar_State* state = (GUI_Scrollbar_State*)GUI_Control_Data( gui, control );
01489 const OPCShape* frame = NULL;
01490 const OPCShape* cthumb = NULL;
01491 bool bFocus = GUI_Control_IsFocused( gui, control );
01492 Rect bound;
01493 int w,h;
01494 GUI_Control_Bound( gui, control, &bound );
01495 w = RectWide(bound);
01496 h = RectHigh(bound);
01497
01498
01499 #define CalcPos(value,x,y)\
01500 {\
01501 int vtotal = state->vmax-state->vmin;\
01502 int vcurr = min(max(value,state->vmin),state->vmax);\
01503 if( w > h )\
01504 {\
01505 x = bound.left + (w * ((vcurr)-state->vmin) / vtotal);\
01506 y = bound.top + (h/2);\
01507 }\
01508 else\
01509 {\
01510 x = bound.left + (w/2);\
01511 y = bound.bottom - (h * ((vcurr)-state->vmin) / vtotal);\
01512 }\
01513 }
01514
01515 #define CalcThumb(x,y)\
01516 {\
01517 x = (x - cthumb->xOff) - (cthumb->wide/2);\
01518 y = (y - cthumb->yOff) - (cthumb->high/2);\
01519 }
01520
01521 #if defined(GUI_GetKeyHeld)
01522 #define SB_SETUP_REPEAT(key) \
01523 if( state->msRepeat && key != state->keyPrev )\
01524 {\
01525 state->msPrev = (unsigned)GUI_MSTime() + GUI_RepeatPause(state->msRepeat);\
01526 state->keyPrev = (key);\
01527 }
01528 #define SB_REPEAT_CANCEL() \
01529 {\
01530 state->msPrev = 0;\
01531 state->keyPrev = 0;\
01532 }
01533 #else
01534 #define SB_SETUP_REPEAT(key)
01535 #define SB_REPEAT_CANCEL()
01536 #endif
01537
01538 switch( msg )
01539 {
01540 case GUI_Cycle:
01541 if( state->basic.frames )
01542 {
01543 cthumb = bFocus && state->basic.frames[guisp_ThumbFocus] ? state->basic.frames[guisp_ThumbFocus] : state->basic.frames[guisp_Thumb];
01544 frame = state->basic.frames[guisp_Frame];
01545 if( bFocus )
01546 {
01547 int value = state->value;
01548 unsigned keypress;
01549 #if defined(GUI_GetKeyHeld)
01550 if( state->keyPrev && state->msRepeat )
01551 {
01552 keypress = GUI_GetKeyHeld() & state->keyPrev;
01553 if( keypress && state->msPrev )
01554 {
01555 unsigned mstime = (unsigned)GUI_MSTime();
01556 if( mstime > state->msPrev && mstime - state->msPrev >= state->msRepeat )
01557 {
01558 state->msPrev = mstime;
01559 }
01560 else
01561 {
01562 keypress = 0;
01563 }
01564 }
01565 else
01566 {
01567 SB_REPEAT_CANCEL();
01568 }
01569 }
01570 else
01571 #endif
01572 {
01573 keypress = GUI_GetKeyPress();
01574 }
01575
01576
01577
01578
01579
01580
01581
01582
01583 #if defined(GUI_GetPointer)
01584 {
01585 int x, y;
01586 GUI_GetPointer(x,y);
01587
01588
01589
01590
01591
01592
01593 if( RectPtInRect( bound, x, y ) )
01594 {
01595 #if defined(GUI_GetKeyHeld)
01596 if( GUI_PICK == GUI_GetKeyPress() || GUI_PICK == GUI_GetKeyHeld() )
01597 #else
01598 if( GUI_PICK == GUI_GetKeyPress() && RectPtInRect( bound, x, y ) )
01599 #endif
01600 {
01601
01602 int vtotal = state->vmax-state->vmin;
01603 if( w > h )
01604 {
01605 int offset = x - bound.left;
01606 int mod = max(h/vtotal,1);
01607 int offsetdown = offset/mod*mod;
01608 int offsetup = (offset+mod)/mod*mod;
01609 if( offset-offsetdown < offsetup-offset )
01610 value = (vtotal * offsetdown / w );
01611 else
01612 value = (vtotal * offsetup / w );
01613 }
01614 else
01615 {
01616 int offset = bound.bottom - y;
01617 int mod = max(h/vtotal,1);
01618 int offsetdown = offset/mod*mod;
01619 int offsetup = (offset+mod)/mod*mod;
01620 if( offset-offsetdown < offsetup-offset )
01621 value = (vtotal * offsetdown / h );
01622 else
01623 value = (vtotal * offsetup / h );
01624 }
01625 }
01626 }
01627 }
01628 #endif
01629 #if (defined(GUI_TABLEFT) && defined(GUI_TABRIGHT) && defined(GUI_TABUP) && defined(GUI_TABDOWN))
01630 if( w > h )
01631 {
01632 if( GUI_TABLEFT == keypress )
01633 {
01634 value--;
01635 if( value < state->vmin )
01636 value = state->vmin;
01637 SB_SETUP_REPEAT(keypress);
01638 }
01639 else if( GUI_TABRIGHT == keypress )
01640 {
01641 value++;
01642 if( value > state->vmax )
01643 value = state->vmax;
01644 SB_SETUP_REPEAT(keypress);
01645 }
01646 else if( GUI_tabhandler( gui ) )
01647 {
01648 SB_REPEAT_CANCEL();
01649 state->oldValue = state->value+1;
01650 }
01651 }
01652 else
01653 {
01654 if( GUI_TABUP == keypress )
01655 {
01656 value++;
01657 if( value > state->vmax )
01658 value = state->vmax;
01659 SB_SETUP_REPEAT(keypress);
01660 }
01661 else if( GUI_TABDOWN == keypress )
01662 {
01663 value--;
01664 if( value < state->vmin )
01665 value = state->vmin;
01666 SB_SETUP_REPEAT(keypress);
01667 }
01668 else if( GUI_SELECT == keypress )
01669 {
01670 value++;
01671 if( value > state->vmax )
01672 value = state->vmin;
01673 SB_SETUP_REPEAT(keypress);
01674 }
01675 else if( GUI_tabhandler( gui ) )
01676 {
01677 SB_REPEAT_CANCEL();
01678 state->oldValue = state->value+1;
01679 }
01680 }
01681 #elif !defined(GUI_GetPointer) && (defined(GUI_TAB) || defined(GUI_TABLEFT) || defined(GUI_TABRIGHT) || defined(GUI_TABUP) || defined(GUI_TABDOWN))
01682
01683 if( GUI_SELECT == keypress )
01684 {
01685 value++;
01686 if( value > state->vmax )
01687 value = state->vmin;
01688 SB_SETUP_REPEAT(keypress);
01689 }
01690 else
01691 {
01692 SB_REPEAT_CANCEL();
01693 if( GUI_tabhandler( gui ) )
01694 {
01695 state->oldValue = state->value+1;
01696 }
01697 }
01698 #endif
01699
01700 state->value = value;
01701 }
01702 else
01703 {
01704 SB_REPEAT_CANCEL();
01705 }
01706 if( state->oldValue != state->value )
01707 {
01708 Rect rthumb;
01709 int x,y;
01710
01711
01712 GUI_Dirty_Rect( gui, &bound );
01713
01714
01715 CalcPos(state->oldValue, x,y);
01716 CalcThumb(x,y);
01717 OPC_NAMING(Shape_Bound)( &rthumb, cthumb, x, y );
01718 GUI_Dirty_Rect( gui, &rthumb );
01719
01720
01721 CalcPos(state->value, x,y);
01722 CalcThumb(x,y);
01723 OPC_NAMING(Shape_Bound)( &rthumb, cthumb, x, y );
01724 GUI_Dirty_Rect( gui, &rthumb );
01725
01726 state->oldValue = state->value;
01727
01728
01729 GUI_ScrollSound();
01730 GUI_Control_Notify( gui, control );
01731 }
01732 }
01733 else
01734 {
01735 if( GUI_Control_IsFocused( gui, control ) )
01736 GUI_tabright(gui);
01737 SB_REPEAT_CANCEL();
01738 return;
01739 }
01740 break;
01741
01742 case GUI_Paint:
01743 if( state->basic.frames )
01744 {
01745 OPC opc;
01746 if( GUI_Control_Paint( gui, control, &opc ) )
01747 {
01748 int x,y;
01749 const OPCShape* shape;
01750 cthumb = bFocus && state->basic.frames[guisp_ThumbFocus] ? state->basic.frames[guisp_ThumbFocus] : state->basic.frames[guisp_Thumb];
01751 frame = bFocus && state->basic.frames[guisp_Focus] ? state->basic.frames[guisp_Focus] : state->basic.frames[guisp_Frame];
01752 CalcPos(state->value, x,y);
01753
01754
01755 OPC_NAMING(Shape)( &opc, frame, bound.left,bound.top );
01756
01757
01758 if( bFocus )
01759 OPC_NAMING(Shape)( &opc, state->basic.frames[guisp_FocusUnder], bound.left,bound.top );
01760
01761
01762 shape = state->basic.frames[guisp_Fill1];
01763 if( shape )
01764 {
01765 OPC clip;
01766 Rect scaling;
01767 OPC_NAMING(Shape_Bound)( &scaling, shape, bound.left,bound.top );
01768 if( w > h )
01769 scaling.right = x+1;
01770 else
01771 scaling.bottom = y+1;
01772 OPC_NAMING(Clip)( &clip, &opc, &scaling );
01773 OPC_NAMING(Shape)( &clip, shape, bound.left,bound.top );
01774 }
01775
01776
01777 shape = state->basic.frames[guisp_Fill2];
01778 if( shape )
01779 {
01780 OPC clip;
01781 Rect scaling;
01782 if( w > h )
01783 scaling.left = x;
01784 else
01785 scaling.top = y;
01786 OPC_NAMING(Shape_Bound)( &scaling, shape, bound.left,bound.top );
01787 OPC_NAMING(Clip)( &clip, &opc, &scaling );
01788 OPC_NAMING(Shape)( &clip, shape, bound.left,bound.top );
01789 }
01790
01791 if( state->basic.text && *state->basic.text )
01792 {
01793
01794 GUI_DrawText( &opc, &bound, state->basic.align, state->basic.text, ~0u );
01795 }
01796
01797
01798 if( bFocus )
01799 OPC_NAMING(Shape)( &opc, state->basic.frames[guisp_FocusOver], bound.left,bound.top );
01800
01801
01802 CalcThumb(x,y);
01803 OPC_NAMING(Shape)( &gui->opc, cthumb, x,y );
01804 }
01805 }
01806 break;
01807 case GUI_Init:
01808 {
01809 GUI_Def_State(gui,control,GUICS_DEFAULT,GUI_CENTER|GUI_VCENTER);
01810 SB_REPEAT_CANCEL();
01811 state->msRepeat = GUI_DefaultRepeat;
01812 state->vmax = 10;
01813 state->value = 5;
01814 state->vmin = 0;
01815 state->oldValue = -1;
01816 }
01817 break;
01818 default:
01819 break;
01820 }
01821 #undef CalcThumb
01822 #undef CalcPos
01823 #undef SB_SETUP_REPEAT
01824 #undef SB_REPEAT_CANCEL
01825 }
01826
01836 int _GUI_Scrollbar_SetValue( struct GUI* gui, int idControl, int newValue, int minValue, int maxValue )
01837 {
01838 int oldvalue;
01839 GUI_Scrollbar_State* tmpScrollbarState = (GUI_Scrollbar_State*)GUI_Control_Get_Data( (gui), (idControl) );
01840 GUI_Assert_Type( (gui), (idControl), guih_Scrollbar );
01841 tmpScrollbarState->vmin = (minValue);
01842 tmpScrollbarState->vmax = (maxValue);
01843 tmpScrollbarState->oldValue = -1-newValue;
01844 oldvalue = tmpScrollbarState->value;
01845 tmpScrollbarState->value = newValue;
01846 if( !(tmpScrollbarState->basic.mask & (GUICS_INVISIBLE|GUICS_NOFOCUS)) )
01847 tmpScrollbarState->basic.mask |= GUICS_NOTIFY;
01848 return oldvalue;
01849 }
01850
01851
01855 void GUI_Ctrl_Ticker( struct GUI* gui, const struct GUI_Control* control, GUI_Message msg )
01856 {
01857 switch( msg )
01858 {
01859 case GUI_Cycle:
01860 {
01861 GUI_Ticker_State* state = (GUI_Ticker_State*)GUI_Control_Data( gui, control );
01862 unsigned mscurr = (unsigned)GUI_MSTime();
01863 if( (!state->basic.frames && !state->basic.text) || (state->basic.mask & GUICS_INVISIBLE) )
01864 return;
01865 if( mscurr < state->msprev )
01866 {
01867
01868 if( state->msprev - mscurr > 30000u )
01869 state->msprev = mscurr;
01870 else
01871 return;
01872 }
01873 if( (mscurr-state->msprev) >= state->msframe )
01874 {
01875 if( state->tWide > RectWide(control->bound) )
01876 {
01877 state->offset++;
01878 if( state->offset > state->tWide )
01879 {
01880 if( state->szNext )
01881 {
01882
01883
01884 GUI_Ticker_SetText( gui, GUI_Control_Index( gui, control ), state->szNext );
01885 state->szNext = NULL;
01886 GUI_Control_Notify( gui, control );
01887 }
01888 else
01889 {
01890 state->offset = 0;
01891 }
01892 }
01893 GUI_Control_Dirty( gui, control );
01894 }
01895 state->msprev = mscurr;
01896 }
01897 }
01898 break;
01899 case GUI_Paint:
01900 {
01901 OPC opc;
01902 if( GUI_Control_Paint( gui, control, &opc ) )
01903 {
01904 GUI_Ticker_State* state = (GUI_Ticker_State*)GUI_Control_Data( gui, control );
01905 Rect bound;
01906 GUI_Control_Bound( gui, control, &bound );
01907 if( state->basic.text )
01908 {
01909
01910
01911 Rect tBound = bound;
01912 tBound.left = tBound.left - state->offset;
01913 tBound.right = tBound.left + state->tWide;
01914 GUI_DrawText( &opc, &tBound, GUI_ONELINE|GUI_VCENTER, state->basic.text, ~0u );
01915 tBound.left += state->tWide;
01916 tBound.right += state->tWide;
01917 if( tBound.left < bound.right )
01918 GUI_DrawText( &opc, &tBound, GUI_ONELINE|GUI_VCENTER, state->basic.text, ~0u );
01919 }
01920 else
01921 {
01922
01923
01924 int xOff = bound.left - state->offset;
01925 {
01926 pointer_foreach_const( OPCShape*, state->basic.frames, control->cState, shape )
01927 {
01928 OPC_NAMING(Shape)( &opc, *shape, xOff-(*shape)->xOff, bound.top - (*shape)->yOff );
01929 xOff += (*shape)->wide;
01930 }
01931 }
01932 if( xOff < bound.right )
01933 {
01934 pointer_foreach_const( OPCShape*, state->basic.frames, control->cState, shape )
01935 {
01936 OPC_NAMING(Shape)( &opc, *shape, xOff-(*shape)->xOff, bound.top - (*shape)->yOff );
01937 xOff += (*shape)->wide;
01938 }
01939 }
01940 }
01941 }
01942 }
01943 break;
01944 case GUI_Init:
01945 {
01946 GUI_Ticker_State* state = (GUI_Ticker_State*)GUI_Control_Data( gui, control );
01947 GUI_Def_State(gui,control,GUICS_NOFOCUS,GUI_LEFT);
01948 GUI_Ticker_SetText( gui, GUI_Control_Index(gui,control), NULL );
01949 state->msframe = 33;
01950 state->msprev = (unsigned)GUI_MSTime() + 3000u;
01951 state->szNext = NULL;
01952 }
01953 break;
01954 default:
01955 break;
01956 }
01957 }
01958
01965 void _GUI_Ticker_SetText( struct GUI* gui, int idControl, const GUI_CHAR* sz )
01966 {
01967 const GUI_Control* control = GUI_Control_Get( gui, idControl );
01968 GUI_Ticker_State* state = (GUI_Ticker_State*)GUI_Control_Data( gui, control );
01969 GUI_Assert_Type( gui, idControl, guih_Ticker );
01970 if( sz )
01971 {
01972 Rect bounds = RectAutoClear();
01973 GUI_MeasureText( &bounds, GUI_ONELINE, sz, ~0u );
01974 state->basic.text = sz;
01975 state->offset = 0;
01976 state->tWide = RectWide(bounds);
01977 }
01978 else
01979 {
01980 state->basic.text = NULL;
01981 state->offset = 0;
01982 state->tWide = 0;
01983 {
01984 pointer_foreach_const( OPCShape*, state->basic.frames, control->cState, curr )
01985 state->tWide += (*curr)->wide;
01986 }
01987 }
01988 }
01989
01993 void _GUI_Ticker_SetSpeed( struct GUI* gui, int idControl, unsigned msDelay, unsigned msframe )
01994 {
01995 const GUI_Control* control = GUI_Control_Get( gui, idControl );
01996 GUI_Ticker_State* state = (GUI_Ticker_State*)GUI_Control_Data( gui, control );
01997 state->msframe = msframe;
01998 state->msprev = (unsigned)GUI_MSTime() + msDelay;
01999 }
02000
02001
02002
02003
02004 static void GUI_AlignShape( const OPC* opc, const Rect* rBound, const OPCShape* shape, unsigned mask )
02005 {
02006 Rect rAligned = *rBound;
02007 Rect rShape;
02008 OPC_NAMING(Shape_Bound)( &rShape, shape, rBound->left, rBound->top );
02009 rAligned = rShape;
02010 switch( mask & 0xc )
02011 {
02012 case GUI_VCENTER:
02013 RectCenterOnY(rAligned,RectCenterY(*rBound));
02014 break;
02015 case GUI_BOTTOM:
02016 RectBottomTo(rAligned,rBound->bottom);
02017 break;
02018 default:
02019 break;
02020 }
02021 switch( mask & 3 )
02022 {
02023 default:
02024 break;
02025 case GUI_CENTER:
02026 RectCenterOnX(rAligned,RectCenterX(*rBound));
02027 break;
02028 case GUI_RIGHT:
02029 RectRightTo(rAligned,rBound->right);
02030 break;
02031 }
02032 OPC_NAMING(Shape)( opc, shape, rBound->left+(rAligned.left-rShape.left), rBound->top+(rAligned.top-rShape.top) );
02033
02034 }
02035
02036
02037
02038
02039 static void GUI_Ctrl_Tumbler_Rects( struct GUI* gui, const struct GUI_Control* control, Rect* rWin, Rect* rLeft, Rect* rRight )
02040 {
02041 GUI_Tumbler_State* state = (GUI_Tumbler_State*)GUI_Control_Data( gui, control );
02042 Rect bound;
02043 GUI_Control_Bound( gui, control, &bound );
02044 OPC_NAMING(Shape_Bound)( rLeft, state->basic.frames[guitb_LBn]?state->basic.frames[guitb_LBn]:state->basic.frames[guitb_LBnHi], bound.left, bound.top );
02045 OPC_NAMING(Shape_Bound)( rRight, state->basic.frames[guitb_RBn]?state->basic.frames[guitb_RBn]:state->basic.frames[guitb_RBnHi], bound.left, bound.top );
02046 if( control->params )
02047 {
02048 *rWin = *((const Rect*)control->params);
02049 RectMoveBy(*rWin, bound.left, bound.top );
02050 }
02051 else
02052 {
02053 if( state->basic.frames[guitb_Overlay] )
02054 OPC_NAMING(Shape_Bound)( rWin, state->basic.frames[guitb_Overlay], bound.left, bound.top );
02055 else if( state->basic.frames[guitb_FocusOver] )
02056 OPC_NAMING(Shape_Bound)( rWin, state->basic.frames[guitb_FocusOver], bound.left, bound.top );
02057 else if( state->basic.frames[guitb_Under] )
02058 OPC_NAMING(Shape_Bound)( rWin, state->basic.frames[guitb_Under], bound.left, bound.top );
02059 else if( state->basic.frames[guitb_FocusUnder] )
02060 OPC_NAMING(Shape_Bound)( rWin, state->basic.frames[guitb_FocusUnder], bound.left, bound.top );
02061 else
02062 *rWin = bound;
02063 }
02064 }
02065
02069 void GUI_Ctrl_Tumbler( struct GUI* gui, const struct GUI_Control* control, GUI_Message msg )
02070 {
02071 GUI_Tumbler_State* state = (GUI_Tumbler_State*)GUI_Control_Data( gui, control );
02072 Rect bound;
02073 GUI_Control_Bound( gui, control, &bound );
02074 #if defined(GUI_GetKeyHeld)
02075 #define TB_SETUP_REPEAT(key) \
02076 if( state->msRepeat && key != state->keyPrev )\
02077 {\
02078 state->msPrev = (unsigned)GUI_MSTime() + GUI_RepeatPause(state->msRepeat);\
02079 state->keyPrev = (key);\
02080 }
02081 #define TB_REPEAT_CANCEL() \
02082 {\
02083 state->msPrev = 0;\
02084 state->keyPrev = 0;\
02085 }
02086 #else
02087 #define TB_SETUP_REPEAT(key)
02088 #define TB_REPEAT_CANCEL()
02089 #endif
02090 switch( msg )
02091 {
02092 case GUI_Cycle:
02093 if( (state->basic.mask & (GUICS_INVISIBLE|GUICS_NOFOCUS)) )
02094 return;
02095 if( state->cStates )
02096 {
02097 Rect rRightArrow, rLeftArrow, rWin;
02098 GUI_Ctrl_Tumbler_Rects( gui, control, &rWin, &rLeftArrow, &rRightArrow );
02099 if( state->stateCurr != state->statePrev )
02100 {
02101 GUI_Control_Dirty( gui, control );
02102
02103
02104
02105
02106 if( state->cTransition > 0 )
02107 {
02108 state->offPrev += RectWide(rWin) / state->cTransition;
02109 if( state->cTransition && state->offPrev >= RectWide(rWin) )
02110 {
02111
02112
02113
02114 state->statePrev = state->stateCurr;
02115 state->offPrev = 0;
02116 return;
02117 }
02118 else
02119 {
02120
02121
02122
02123 return;
02124 }
02125 }
02126 else
02127 {
02128 state->statePrev = state->stateCurr;
02129 state->offPrev = 0;
02130 }
02131 }
02132 if( GUI_Control_IsFocused( gui, control ) )
02133 {
02134 unsigned keypress;
02135 #if defined(GUI_GetKeyHeld)
02136 if( state->keyPrev && state->msRepeat )
02137 {
02138 keypress = GUI_GetKeyHeld() & state->keyPrev;
02139 if( keypress && state->msPrev )
02140 {
02141 unsigned mstime = (unsigned)GUI_MSTime();
02142 if( mstime > state->msPrev && mstime - state->msPrev >= state->msRepeat )
02143 {
02144 state->msPrev = mstime;
02145 }
02146 else
02147 {
02148 keypress = 0;
02149 }
02150 }
02151 else
02152 {
02153 TB_REPEAT_CANCEL();
02154 }
02155 }
02156 else
02157 #endif
02158 {
02159 keypress = GUI_GetKeyPress();
02160 }
02161
02162
02163
02164
02165 #if defined(GUI_GetPointer)
02166 if( keypress == GUI_PICK )
02167 {
02168 int x,y;
02169 GUI_GetPointer(x,y);
02170 if( RectPtInRect( rRightArrow, x,y) )
02171 {
02172 state->stateCurr++;
02173 if( state->stateCurr >= state->cStates )
02174 state->stateCurr = 0;
02175 GUI_ClearKeyPress();
02176 TB_SETUP_REPEAT(keypress);
02177 }
02178 else if( RectPtInRect( rLeftArrow, x,y ) )
02179 {
02180 state->stateCurr--;
02181 if( state->stateCurr < 0 )
02182 state->stateCurr = state->cStates - 1;
02183 GUI_ClearKeyPress();
02184 TB_SETUP_REPEAT(keypress);
02185 }
02186 else
02187 {
02188 TB_REPEAT_CANCEL();
02189 }
02190 }
02191 #endif
02192 #if (defined(GUI_TABLEFT) && defined(GUI_TABRIGHT) && defined(GUI_TABUP) && defined(GUI_TABDOWN))
02193 if( abs(rLeftArrow.top - rRightArrow.top) > abs(rLeftArrow.left - rRightArrow.left) )
02194 {
02195 if( GUI_TABUP == keypress )
02196 {
02197 state->stateCurr--;
02198 if( state->stateCurr < 0 )
02199 state->stateCurr = state->cStates - 1;
02200 GUI_ClearKeyPress();
02201 TB_SETUP_REPEAT(keypress);
02202 }
02203 else if( GUI_TABDOWN == keypress )
02204 {
02205 state->stateCurr++;
02206 if( state->stateCurr >= state->cStates )
02207 state->stateCurr = 0;
02208 GUI_ClearKeyPress();
02209 TB_SETUP_REPEAT(keypress);
02210 }
02211 else if( GUI_tabhandler( gui ) )
02212 {
02213 TB_REPEAT_CANCEL();
02214 return;
02215 }
02216 }
02217 else
02218 {
02219 if( GUI_TABLEFT == keypress )
02220 {
02221 state->stateCurr--;
02222 if( state->stateCurr < 0 )
02223 state->stateCurr = state->cStates - 1;
02224 GUI_ClearKeyPress();
02225 TB_SETUP_REPEAT(keypress);
02226 }
02227 else if( GUI_TABRIGHT == keypress )
02228 {
02229 state->stateCurr++;
02230 if( state->stateCurr >= state->cStates )
02231 state->stateCurr = 0;
02232 GUI_ClearKeyPress();
02233 TB_SETUP_REPEAT(keypress);
02234 }
02235 else if( GUI_tabhandler( gui ) )
02236 {
02237 TB_REPEAT_CANCEL();
02238 return;
02239 }
02240 }
02241 #elif !defined(GUI_GetPointer) && (defined(GUI_TAB) || defined(GUI_TABLEFT) || defined(GUI_TABRIGHT) || defined(GUI_TABUP) || defined(GUI_TABDOWN))
02242
02243
02244
02245 if( GUI_SELECT == keypress )
02246 {
02247 state->stateCurr++;
02248 if( state->stateCurr >= state->cStates )
02249 state->stateCurr = 0;
02250 GUI_ClearKeyPress();
02251 TB_SETUP_REPEAT(keypress);
02252 }
02253 else if( GUI_tabhandler( gui ) )
02254 {
02255 TB_REPEAT_CANCEL();
02256 return;
02257 }
02258 #endif
02259 if( state->stateCurr != state->statePrev )
02260 {
02261 GUI_Tabsound();
02262 GUI_Control_Notify( gui, control );
02263 }
02264 }
02265 else
02266 {
02267 TB_REPEAT_CANCEL();
02268 }
02269 }
02270 else
02271 {
02272 if( GUI_Control_IsFocused( gui, control ) )
02273 GUI_tabright(gui);
02274 TB_REPEAT_CANCEL();
02275 return;
02276 }
02277 break;
02278 case GUI_Paint:
02279 {
02280 OPC opc;
02281 if( !state->cStates || !state->basic.frames || (state->basic.mask & GUICS_INVISIBLE) )
02282 return;
02283 if( GUI_Control_Paint( gui, control, &opc ) )
02284 {
02285 Rect rRightArrow, rLeftArrow, rWin;
02286 bool bFocus = GUI_Control_IsFocused( gui, control );
02287 const OPCShape* la = state->basic.frames[guitb_LBn];
02288 const OPCShape* ra = state->basic.frames[guitb_RBn];
02289 int offx = 0,offy = 0;
02290 GUI_Ctrl_Tumbler_Rects( gui, control, &rWin, &rLeftArrow, &rRightArrow );
02291 if( bFocus && state->basic.frames[guitb_FocusUnder] )
02292 {
02293 OPC_NAMING(Shape)( &opc, state->basic.frames[guitb_FocusUnder], bound.left, bound.top );
02294 }
02295 else
02296 {
02297 OPC_NAMING(Shape)( &opc, state->basic.frames[guitb_Under], bound.left, bound.top );
02298 }
02299 if( state->offPrev )
02300 {
02301 if( state->statePrev == 0 && state->stateCurr == state->cStates-1 )
02302 {
02303
02304 la = state->basic.frames[guitb_LBnHi];
02305 if( rLeftArrow.bottom < rRightArrow.top )
02306 {
02307
02308 offy = state->offPrev;
02309 }
02310 else
02311 {
02312
02313 offx = state->offPrev;
02314 }
02315 }
02316 else if( state->statePrev == state->cStates-1 && state->stateCurr == 0 )
02317 {
02318
02319 ra = state->basic.frames[guitb_RBnHi];
02320 if( rLeftArrow.bottom < rRightArrow.top )
02321 {
02322
02323 offy = -state->offPrev;
02324 }
02325 else
02326 {
02327
02328 offx = -state->offPrev;
02329 }
02330 }
02331 else if( state->statePrev < state->stateCurr )
02332 {
02333
02334 ra = state->basic.frames[guitb_RBnHi];
02335 if( rLeftArrow.bottom < rRightArrow.top )
02336 {
02337
02338 offy = -state->offPrev;
02339 }
02340 else
02341 {
02342
02343 offx = -state->offPrev;
02344 }
02345 }
02346 else if( state->statePrev > state->stateCurr )
02347 {
02348
02349 la = state->basic.frames[guitb_LBnHi];
02350 if( rLeftArrow.bottom < rRightArrow.top )
02351 {
02352
02353 offy = state->offPrev;
02354 }
02355 else
02356 {
02357
02358 offx = state->offPrev;
02359 }
02360 }
02361 }
02362
02363 if( state->states || state->tstates )
02364 {
02365 OPC opcbound;
02366 OPC_NAMING(Clip)( &opcbound, &opc, &rWin );
02367 if( offx )
02368 {
02369 RectLeftTo( rWin, rWin.left+offx );
02370 }
02371 else if( offy )
02372 {
02373 RectTopTo( rWin, rWin.top+offy );
02374 }
02375 if( offx || offy )
02376 {
02377 if( state->states )
02378 GUI_AlignShape( &opcbound, &rWin, state->states[state->statePrev], state->ialign );
02379 if( state->tstates )
02380 GUI_DrawText( &opcbound, &rWin, state->basic.align, state->tstates[state->statePrev], ~0u );
02381 }
02382 if( offx < 0 )
02383 {
02384 RectLeftTo( rWin, rWin.left+RectWide(rWin) );
02385 }
02386 else if( offx > 0 )
02387 {
02388 RectLeftTo( rWin, rWin.left-RectWide(rWin) );
02389 }
02390 if( offy < 0 )
02391 {
02392 RectTopTo( rWin, rWin.top+RectHigh(rWin) );
02393 }
02394 else if( offy > 0 )
02395 {
02396 RectTopTo( rWin, rWin.top-RectHigh(rWin) );
02397 }
02398 if( state->states )
02399 GUI_AlignShape( &opcbound, &rWin, state->states[state->stateCurr], state->ialign );
02400 if( state->tstates )
02401 GUI_DrawText( &opcbound, &rWin, state->basic.align, state->tstates[state->stateCurr], ~0u );
02402 }
02403 OPC_NAMING(Shape)( &opc, state->basic.frames[guitb_Overlay], bound.left, bound.top );
02404 if( state->basic.text && *state->basic.text )
02405 {
02406
02407 GUI_DrawText( &opc, &bound, state->basic.align, state->basic.text, ~0u );
02408 }
02409 if( bFocus )
02410 {
02411 OPC_NAMING(Shape)( &opc, state->basic.frames[guitb_FocusOver], bound.left, bound.top );
02412
02413 OPC_NAMING(Shape)( &opc, la, bound.left, bound.top );
02414 OPC_NAMING(Shape)( &opc, ra, bound.left, bound.top );
02415 }
02416 }
02417 }
02418 break;
02419 case GUI_Init:
02420 {
02421 GUI_Def_State(gui,control,GUICS_DEFAULT,GUI_CENTER|GUI_BOTTOM);
02422 TB_REPEAT_CANCEL();
02423 if( state->basic.cFrames > GUITumblerParts_COUNT )
02424 {
02425 GUI_Tumbler_Setup( gui, GUI_Control_Index( gui, control ), state->basic.frames + GUITumblerParts_COUNT, GUI_CENTER|GUI_VCENTER, NULL, GUI_CENTER|GUI_BOTTOM, state->basic.cFrames - GUITumblerParts_COUNT, 8, 0 );
02426 }
02427 else
02428 {
02429 GUI_Tumbler_Setup( gui, GUI_Control_Index( gui, control ), NULL, GUI_CENTER|GUI_VCENTER, NULL, GUI_CENTER|GUI_BOTTOM, 0, 5, 0 );
02430 }
02431 }
02432 break;
02433 default:
02434 break;
02435 }
02436 #undef TB_SETUP_REPEAT
02437 #undef TB_REPEAT_CANCEL
02438 }
02439
02452 void _GUI_Tumbler_Setup( GUI* gui, int id, const OPCShape* const* shapes, unsigned shapeAlign, const GUI_CHAR* const* szz, unsigned szzAlign, size_t count, int transition, int curr )
02453 {
02454 const GUI_Control* control = GUI_Control_Get( gui, id );
02455 GUI_Tumbler_State* state = (GUI_Tumbler_State*)GUI_Control_Data( gui, control );
02456 GUI_Assert_Type( gui, id, guih_Tumbler );
02457 state->basic.align = szzAlign;
02458 state->offPrev = 0;
02459 state->states = shapes;
02460 state->tstates = szz;
02461 state->cStates = (int)count;
02462 state->cTransition = transition;
02463 state->ialign = shapeAlign;
02464 state->stateCurr = state->statePrev = curr;
02465 state->msRepeat = GUI_DefaultRepeat;
02466 if( count && !(state->basic.mask & (GUICS_INVISIBLE|GUICS_NOFOCUS)) )
02467 state->basic.mask |= GUICS_NOTIFY;
02468 GUI_Control_Dirty( gui, control );
02469 }
02470
02477 void _GUI_Tumbler_SetFrame( GUI* gui, int id, int curr )
02478 {
02479 const GUI_Control* control = GUI_Control_Get( gui, id );
02480 GUI_Tumbler_State* state = (GUI_Tumbler_State*)GUI_Control_Data( gui, control );
02481 GUI_Assert_Type( gui, id, guih_Tumbler );
02482 state->offPrev = 0;
02483 state->stateCurr = curr;
02484 state->basic.mask |= GUICS_NOTIFY;
02485 GUI_Control_Dirty( gui, control );
02486 }
02487
02488
02494 void GUI_Ctrl_GUI( struct GUI* gui, const struct GUI_Control* control, GUI_Message msg )
02495 {
02496 GUI_Control_State* state = GUI_Control_Data( gui, control );
02497 GUI* pGui = (GUI*)(state+1);
02498
02499
02500
02501 pGui->parent = gui;
02502 pGui->control = control;
02503 switch( msg )
02504 {
02505 case GUI_PaintCtrl:
02506 case GUI_CycleCtrl:
02507 return;
02508
02509 case GUI_Focus:
02510
02511 if( GUI_Control_IsFocused( gui, control ) )
02512 {
02513
02514 if( pGui->focus < 0 )
02515 {
02516 GUI_SetFocus(pGui,0);
02517 GUI_Control_Dirty( gui, control );
02518 }
02519 }
02520 else
02521 {
02522
02523 if( pGui->focus != -1 )
02524 {
02525
02526 pGui->focus = -1;
02527 GUI_Control_Dirty( gui, control );
02528 }
02529 }
02530 return;
02531
02532 case GUI_Cycle:
02533
02534 if( state->mask & GUICS_INVISIBLE )
02535 return;
02536
02537
02538 pGui->offx = gui->offx + state->offx + control->bound.left;
02539 pGui->offy = gui->offy + state->offy + control->bound.top;
02540 if( (state->mask & (GUICS_INVISIBLE|GUICS_NOFOCUS)) != (GUICS_INVISIBLE|GUICS_NOFOCUS) )
02541 pGui->handler( pGui, GUI_Cycle );
02542
02543 GUI_CallNotifies(pGui);
02544 #ifdef SIMPLE_DIRTY
02545 RectUnionRect( gui->dirty, pGui->dirty );
02546 #endif
02547 return;
02548
02549 case GUI_Paint:
02550
02551 pGui->dirty = gui->dirty;
02552 pGui->offx = gui->offx + state->offx + control->bound.left;
02553 pGui->offy = gui->offy + state->offy + control->bound.top;
02554 pGui->handler( pGui, GUI_Paint );
02555 return;
02556
02557 case GUI_Init:
02558
02559 GUI_Def_State(gui,control,GUICS_DEFAULT,GUI_LEFT);
02560 return;
02561
02562 case GUI_Destroy:
02563 default:
02564 break;
02565 }
02566 pGui->handler( pGui, msg );
02567 }
02568
02569
02576 void _GUI_Default( struct GUI* gui, GUI_Message msg )
02577 {
02578 switch( msg )
02579 {
02580
02581 case GUI_CycleCtrl:
02582
02583
02584
02585
02586
02587 GUI_Control_handle( gui, GUI_Control_Get( gui, gui->iControl ), GUI_Cycle );
02588 break;
02589
02590 case GUI_PaintCtrl:
02591
02592
02593
02594
02595
02596 GUI_Control_handle( gui, GUI_Control_Get( gui, gui->iControl ), GUI_Paint );
02597 break;
02598
02599 case GUI_Cycle:
02600 {
02601
02602 pointer_foreach_const( GUI_Control, gui->list, gui->cControl, control )
02603 {
02604 GUI_Control_State* state = GUI_Control_Data( gui, control );
02605 state->mask &= ~GUICS_NOTIFY;
02606 }
02607 }
02608 #ifdef GUI_GetPointer
02609
02610 if( !gui->parent || GUI_Control_IsFocused( gui->parent, gui->control ) )
02611 {
02612 int x, y;
02613 Rect bound;
02614 GUI_GetPointer( x, y );
02615 {
02616 pointer_foreach_const_reverse( GUI_Control, gui->list, gui->cControl, control )
02617 {
02618 GUI_Control_Bound( gui, control, &bound );
02619 if( !(GUI_Control_Data( gui, control )->mask & (GUICS_INVISIBLE|GUICS_NOFOCUS)) && RectPtInRect( bound, x, y ) )
02620 {
02621 if( gui->focus >= 0 )
02622 {
02623 const GUI_Control* oldFocus = GUI_Control_Get( gui, gui->focus );
02624 if( oldFocus != control )
02625 {
02626 GUI_Control_Dirty( gui, oldFocus );
02627 GUI_Control_Dirty( gui, control );
02628 gui->focus = control - gui->list;
02629 gui->mask |= GUIM_FOCUSCHANGED;
02630 }
02631 }
02632 else
02633 {
02634 gui->focus = control - gui->list;
02635 GUI_Control_Dirty( gui, control );
02636 gui->mask |= GUIM_FOCUSCHANGED;
02637 }
02638 break;
02639 }
02640 }
02641 }
02642 }
02643 #endif
02644
02645 for( gui->iControl = 0; gui->iControl < gui->cControl; ++gui->iControl )
02646 gui->handler(gui, GUI_CycleCtrl);
02647 break;
02648
02649 case GUI_Paint:
02650
02651
02652
02653
02654
02655
02656 {
02657 OPC opc;
02658 const Rect* curr;
02659 #ifdef SIMPLE_DIRTY
02660 if( RectEmpty(gui->dirty) )
02661 {
02662 return;
02663 }
02664 else
02665 {
02666 curr = &gui->dirty;
02667 }
02668 gui->mask |= GUIM_INPAINT;
02669 #else
02670 int cDirty;
02671 if( gui->parent )
02672 {
02673
02674 curr = &gui->parent->dirty;
02675 cDirty = 1;
02676 }
02677 else
02678 {
02679
02680 curr = gui->cdirty->dirty;
02681 cDirty = gui->cdirty->cDirty;
02682 }
02683
02684 gui->mask |= GUIM_INPAINT;
02685 while( cDirty-- )
02686 #endif
02687 {
02688
02689 gui->dirty = *curr;
02690 OPC_NAMING(Clip)( &opc, &gui->opc, curr );
02691
02692 OPC_NAMING(Shape)( &opc, gui->bg, gui->offx,gui->offy );
02693
02694 for( gui->iControl = 0; gui->iControl < gui->cControl; ++gui->iControl )
02695 {
02696
02697 if( !( GUI_Control_Get_Mask( gui, gui->iControl ) & GUICS_INVISIBLE) )
02698 {
02699 gui->handler(gui, GUI_PaintCtrl);
02700 }
02701 }
02702
02703 OPC_NAMING(Shape)( &opc, gui->ov, gui->offx,gui->offy );
02704 curr++;
02705 }
02706
02707 gui->mask &= ~GUIM_INPAINT;
02708
02709 }
02710 RectClear(gui->dirty);
02711 break;
02712
02713 case GUI_Init:
02714 {
02715
02716 GUI_Dirty( gui );
02717 {
02718
02719 pointer_foreach_const( GUI_Control, gui->list, gui->cControl, control )
02720 GUI_Control_handle( gui, control, GUI_Init );
02721 }
02722
02723 GUI_SetFocus( gui, 0 );
02724 gui->mask = GUIM_ALIVE;
02725 }
02726 break;
02727
02728 case GUI_Destroy:
02729 {
02730 pointer_foreach_const( GUI_Control, gui->list, gui->cControl, control )
02731 GUI_Control_handle( gui, control, GUI_Destroy );
02732 GUI_Dirty_Rect( gui, &gui->opc.clip );
02733 gui->cControl = 0;
02734 gui->mask = 0;
02735 }
02736 break;
02737
02738
02739 case GUI_Focus:
02740 case GUI_Notify:
02741 default:
02742 break;
02743 }
02744 }
02745
02746 #ifndef NO_GUI_BLIB
02747
02748 #include "ctl/blib.h"
02749
02750
02751
02752 #define XENUM(tag,verbose,data) sizeof(data),
02753 static const size_t lutRequirements[] =
02754 {
02755 EDEF_HANDLERS(XENUM)
02756 };
02757 #undef XENUM
02758
02776 size_t GUI_BlibNeeds( const void* pData, size_t size, size_t myExtra )
02777 {
02778
02779
02780
02781
02782
02783 const BLIB* blib = pData;
02784 if( BLIB_Valid( blib, size ) && BLIB_User(blib) == *((uint32*)"GUI") )
02785 {
02786 size_t ret = (sizeof(GUI) + myExtra + 7) & ~7u;
02787 BLIB_foreach(blib,curr)
02788 {
02789 const BLIB* blibCurr = (const BLIB*)curr;
02790 uint32 user = BLIB_User( blibCurr );
02791 if( user >= GUIHandlers_COUNT )
02792 return 0;
02793
02794 switch( user )
02795 {
02796 case guih_Invalid: default:
02797 return 0;
02798
02799 case guih_Background:
02800 case guih_Overlay:
02801 break;
02802
02803 case guih_GUI:
02804 case guih_ArtResource:
02805 case guih_StaticFrame:
02806 case guih_Button:
02807 case guih_Checkbox:
02808 case guih_Animation:
02809 case guih_Scrollbar:
02810 case guih_Ticker:
02811 case guih_Tumbler:
02812 ret += lutRequirements[user] + sizeof(GUI_Control) + sizeof(GUI_Control*) + sizeof(GUI_Control*) + (BLIB_Count( blibCurr ) * sizeof(OPCShape*));
02813 break;
02814
02815 }
02816 }
02817 return ret;
02818 }
02819 return 0;
02820 }
02821
02822
02823 int qsGCA_vtab( const GUI_Control** p1, const GUI_Control** p2 )
02824 {
02825 int diffX, diffY, x1, y1, x2, y2;
02826 RectCenterPt((*p1)->bound,x1,y1);
02827 RectCenterPt((*p2)->bound,x2,y2);
02828 diffY = y1-y2;
02829 diffX = x1-x2;
02830 if( abs( diffX ) > GUI_TAB_IGNORE )
02831 return diffX;
02832 return diffY;
02833 }
02834
02835
02836
02837 int qsGCA_htab( const GUI_Control** p1, const GUI_Control** p2 )
02838 {
02839 int diffX, diffY, x1, y1, x2, y2;
02840 RectCenterPt((*p1)->bound,x1,y1);
02841 RectCenterPt((*p2)->bound,x2,y2);
02842 diffY = y1-y2;
02843 diffX = x1-x2;
02844 if( abs(diffY) > GUI_TAB_IGNORE )
02845 return diffY;
02846 return diffX;
02847 }
02848
02880 GUI* GUI_BlibInit( const void* pData, size_t size, size_t myExtra, void* pguiBuff, GUI_handler handler, void* param, const OPC* opc
02881 #ifdef SIMPLE_DIRTY
02882 )
02883 #else
02884 , ClipRect* cliprect )
02885 #endif
02886 {
02887 GUI* gui = (GUI*)pguiBuff;
02888 const BLIB* blib = pData;
02889 myExtra = (myExtra + 7) & ~7;
02890 if( BLIB_Valid( blib, size ) && BLIB_User(blib) == *((uint32*)"GUI") )
02891 {
02892
02893
02894
02895 GUI_Control* list;
02896 GUI_Control** htab;
02897 GUI_Control** vtab;
02898 const OPCShape** sptab;
02899 {
02900 size_t offset = (sizeof(GUI) + myExtra + 7) & ~7u;
02901 size_t count = 0;
02902 size_t cControl = 0;
02903 BLIB_foreach(blib,curr)
02904 {
02905 const BLIB* blibCurr = (const BLIB*)curr;
02906 GUIHandlers user = (GUIHandlers)BLIB_User( blibCurr );
02907 if( user >= GUIHandlers_COUNT )
02908 return 0;
02909 switch( user )
02910 {
02911 case guih_Invalid: default:
02912 return NULL;
02913
02914 case guih_Background:
02915 gui->bg = (const OPCShape*)(BLIB_SIZE( blib ) ? BLIB_ELEMENT_PTR( blibCurr, 0 ) : NULL);
02916 break;
02917 case guih_Overlay:
02918 gui->ov = (const OPCShape*)(BLIB_SIZE( blib ) ? BLIB_ELEMENT_PTR( blibCurr, 0 ) : NULL);
02919 break;
02920
02921 case guih_ArtResource:
02922 count++;
02923 break;
02924 case guih_GUI:
02925 user = guih_StaticFrame;
02926 case guih_StaticFrame:
02927 case guih_Button:
02928 case guih_Checkbox:
02929 case guih_Animation:
02930 case guih_Scrollbar:
02931 case guih_Ticker:
02932 case guih_Tumbler:
02933 offset += lutRequirements[user];
02934 count++;
02935 cControl++;
02936 break;
02937 }
02938 }
02939
02940 gui->parent = NULL;
02941 gui->list = list = (GUI_Control*)((uint8*)pguiBuff + offset);
02942 gui->htab = htab = (GUI_Control**)(list + count);
02943 gui->vtab = vtab = (GUI_Control**)(htab + count);
02944 sptab = (const OPCShape**)(vtab + count);
02945 gui->bg = gui->ov = NULL;
02946 gui->cControl = cControl;
02947 gui->focus = 0;
02948 gui->offx = gui->offy = 0;
02949 gui->opc = *opc;
02950 gui->param = param;
02951 #ifndef GUI_NO_GENERATOR
02952 state_init( gui->state );
02953 #endif
02954 gui->dirty = opc->clip;
02955 #ifndef SIMPLE_DIRTY
02956 gui->cdirty = cliprect;
02957 #endif
02958 gui->handler = handler ? handler : _GUI_Default;
02959 }
02960
02961
02962
02963 {
02964 size_t offset = sizeof(GUI);
02965 BLIB_foreach(blib,curr)
02966 {
02967 const BLIB* blibCurr = (const BLIB*)curr;
02968 GUIHandlers user = (GUIHandlers)BLIB_User( blibCurr );
02969 switch( user )
02970 {
02971 case guih_Invalid: default:
02972 return NULL;
02973
02974 case guih_Background:
02975 gui->bg = (const OPCShape*)(BLIB_SIZE( blib ) ? BLIB_ELEMENT_PTR( blibCurr, 0 ) : NULL);
02976 break;
02977 case guih_Overlay:
02978 gui->ov = (const OPCShape*)(BLIB_SIZE( blib ) ? BLIB_ELEMENT_PTR( blibCurr, 0 ) : NULL);
02979 break;
02980
02981 case guih_GUI:
02982 user = guih_StaticFrame;
02983 case guih_ArtResource:
02984 case guih_StaticFrame:
02985 case guih_Button:
02986 case guih_Checkbox:
02987 case guih_Animation:
02988 case guih_Scrollbar:
02989 case guih_Ticker:
02990 case guih_Tumbler:
02991 list->type = user;
02992 list->offData = offset;
02993
02994
02995
02996
02997 assert( BLIB_COUNT( blibCurr ) >= 1 );
02998 list->cState = BLIB_COUNT( blibCurr )-1;
02999 list->state = list->cState ? sptab : NULL;
03000 assert( BLIB_ELEMENT_SIZE( blibCurr, 0 ) == sizeof(Rect) );
03001 list->bound = *((const Rect*)BLIB_ELEMENT_PTR( blibCurr, 0 ));
03002 list->params = NULL;
03003 {
03004 size_t ishape;
03005 for( ishape = 1; ishape <= list->cState; ++ishape )
03006 {
03007 const OPCShape* shape = (const OPCShape*)(BLIB_ELEMENT_SIZE( blibCurr, ishape ) ? BLIB_ELEMENT_PTR( blibCurr, ishape ) : NULL);
03008 *sptab++ = shape;
03009 }
03010 }
03011 offset += lutRequirements[user];
03012 *htab++ = list;
03013 *vtab++ = list++;
03014 break;
03015 }
03016 }
03017 }
03018
03019 array_qsort( GUI_Control*, (GUI_Control**)gui->htab, gui->cControl, qsGCA_htab );
03020 array_qsort( GUI_Control*, (GUI_Control**)gui->vtab, gui->cControl, qsGCA_vtab );
03021
03022
03023 gui->handler(gui,GUI_Init);
03024 return gui;
03025 }
03026 return NULL;
03027 }
03028 #endif