/*
- * freeglut_structure.c
+ * fg_structure.c
*
* Windows and menus need tree structure
*
/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
extern void fgPlatformCreateWindow ( SFG_Window *window );
+extern void fghDefaultReshape(int width, int height, FGCBUserData userData);
static void fghClearCallBacks( SFG_Window *window )
{
{
int i;
for( i = 0; i < TOTAL_CALLBACKS; ++i )
+ {
window->CallBacks[ i ] = NULL;
+ window->CallbackDatas[ i ] = NULL;
+ }
}
}
GLboolean gameMode, GLboolean isMenu )
{
/* Have the window object created */
- SFG_Window *window = (SFG_Window *)calloc( sizeof(SFG_Window), 1 );
+ SFG_Window *window = (SFG_Window *)calloc( 1, sizeof(SFG_Window) );
+
+ if( !window )
+ {
+ fgError( "Out of memory. Could not create window." );
+ }
fgPlatformCreateWindow ( window );
fghClearCallBacks( window );
+ SET_WCB( *window, Reshape, fghDefaultReshape, NULL);
/* Initialize the object properties */
window->ID = ++fgStructure.WindowID;
else
fgListAppend( &fgStructure.Windows, &window->Node );
- /* Set the default mouse cursor and reset the modifiers value */
+ /* Set the default mouse cursor */
window->State.Cursor = GLUT_CURSOR_INHERIT;
- window->IsMenu = isMenu;
-
- window->State.IgnoreKeyRepeat = GL_FALSE;
- window->State.KeyRepeating = GL_FALSE;
- window->State.IsFullscreen = GL_FALSE;
+ /* Mark window as menu if a menu is to be created */
+ window->IsMenu = isMenu;
/*
* Open the window now. The fgOpenWindow() function is system
- * dependant, and resides in freeglut_window.c. Uses fgState.
+ * dependent, and resides in fg_window.c. Uses fgState.
*/
fgOpenWindow( window, title, positionUse, x, y, sizeUse, w, h, gameMode,
(GLboolean)(parent ? GL_TRUE : GL_FALSE) );
/*
* This private function creates a menu and adds it to the menus list
*/
-SFG_Menu* fgCreateMenu( FGCBMenu menuCallback )
+SFG_Menu* fgCreateMenu( FGCBMenuUC menuCallback, FGCBUserData userData )
{
- int x = 100, y = 100, w = 1, h = 1;
SFG_Window *current_window = fgStructure.CurrentWindow;
/* Have the menu object created */
menu->ParentWindow = NULL;
/* Create a window for the menu to reside in. */
-
- fgCreateWindow( NULL, "freeglut menu", GL_TRUE, x, y, GL_TRUE, w, h,
+ fgCreateWindow( NULL, "freeglut menu", GL_FALSE, 0, 0, GL_FALSE, 0, 0,
GL_FALSE, GL_TRUE );
menu->Window = fgStructure.CurrentWindow;
glutDisplayFunc( fgDisplayMenu );
- glutHideWindow( ); /* Hide the window for now */
fgSetWindow( current_window );
/* Initialize the object properties: */
- menu->ID = ++fgStructure.MenuID;
- menu->Callback = menuCallback;
- menu->ActiveEntry = NULL;
+ menu->ID = ++fgStructure.MenuID;
+ menu->Callback = menuCallback;
+ menu->CallbackData = userData;
+ menu->ActiveEntry = NULL;
+ menu->Font = fgState.MenuFont;
fgListInit( &menu->Entries );
fgListAppend( &fgStructure.Menus, &menu->Node );
* to ensure that they are no longer called after this point.
*/
{
- FGCBDestroy destroy = (FGCBDestroy)FETCH_WCB( *window, Destroy );
+ FGCBDestroyUC destroy = (FGCBDestroyUC)FETCH_WCB( *window, Destroy );
+ FGCBUserData destroyData = FETCH_USER_DATA_WCB( *window, Destroy );
fghClearCallBacks( window );
- SET_WCB( *window, Destroy, destroy );
+ SET_WCB( *window, Destroy, destroy, destroyData );
}
}
/*
* This function destroys a window and all of its subwindows. Actually,
- * another function, defined in freeglut_window.c is called, but this is
+ * another function, defined in fg_window.c is called, but this is
* a whole different story...
*/
void fgDestroyWindow( SFG_Window* window )
{
SFG_Menu *activeMenu=fgStructure.CurrentMenu;
fgStructure.CurrentMenu = menu;
- menu->Destroy( );
+ menu->Destroy( menu->DestroyData );
fgStructure.CurrentMenu = activeMenu;
}
* This function should be called on glutInit(). It will prepare the internal
* structure of freeglut to be used in the application. The structure will be
* destroyed using fgDestroyStructure() on glutMainLoop() return. In that
- * case further use of freeglut should be preceeded with a glutInit() call.
+ * case further use of freeglut should be preceded with a glutInit() call.
*/
void fgCreateStructure( void )
{
/*
* Helper function to enumerate through all registered top-level windows
*/
-void fgEnumWindows( FGCBenumerator enumCallback, SFG_Enumerator* enumerator )
+void fgEnumWindows( FGCBWindowEnumerator enumCallback, SFG_Enumerator* enumerator )
{
SFG_Window *window;
}
/*
+* Helper function to enumerate through all registered top-level windows
+*/
+void fgEnumMenus( FGCBMenuEnumerator enumCallback, SFG_Enumerator* enumerator )
+{
+ SFG_Menu *menu;
+
+ FREEGLUT_INTERNAL_ERROR_EXIT ( enumCallback && enumerator,
+ "Enumerator or callback missing from window enumerator call",
+ "fgEnumWindows" );
+
+ /* It's enough to check all entries in fgStructure.Menus... */
+ for( menu = (SFG_Menu *)fgStructure.Menus.First;
+ menu;
+ menu = (SFG_Menu *)menu->Node.Next )
+ {
+ enumCallback( menu, enumerator );
+ if( enumerator->found )
+ return;
+ }
+}
+
+/*
* Helper function to enumerate through all a window's subwindows
* (single level descent)
*/
-void fgEnumSubWindows( SFG_Window* window, FGCBenumerator enumCallback,
+void fgEnumSubWindows( SFG_Window* window, FGCBWindowEnumerator enumCallback,
SFG_Enumerator* enumerator )
{
SFG_Window *child;
/*
* fgWindowByHandle returns a (SFG_Window *) value pointing to the
* first window in the queue matching the specified window handle.
- * The function is defined in freeglut_structure.c file.
+ * The function is defined in fg_structure.c file.
*/
SFG_Window* fgWindowByHandle ( SFG_WindowHandleType hWindow )
{
}
/*
- * This function is similiar to the previous one, except it is
+ * This function is similar to the previous one, except it is
* looking for a specified (sub)window identifier. The function
- * is defined in freeglut_structure.c file.
+ * is defined in fg_structure.c file.
*/
SFG_Window* fgWindowByID( int windowID )
{
SFG_Enumerator enumerator;
- /* Uses a method very similiar for fgWindowByHandle... */
+ /* Uses a method very similar for fgWindowByHandle... */
enumerator.found = GL_FALSE;
enumerator.data = ( void * )&windowID;
fgEnumWindows( fghcbWindowByID, &enumerator );
}
/*
- * Looks up a menu given its ID. This is easier that fgWindowByXXX
+ * A static helper function to look for a menu given its ID
+ */
+static void fghcbMenuByID( SFG_Menu *menu,
+ SFG_Enumerator *enumerator )
+{
+ if ( enumerator->found )
+ return;
+
+ /* Check the menu's ID. */
+ if( menu->ID == *( int *)(enumerator->data) )
+ {
+ enumerator->found = GL_TRUE;
+ enumerator->data = menu;
+
+ return;
+ }
+}
+
+/*
+ * Looks up a menu given its ID. This is easier than fgWindowByXXX
* as all menus are placed in one doubly linked list...
*/
SFG_Menu* fgMenuByID( int menuID )
{
- SFG_Menu *menu = NULL;
+ SFG_Enumerator enumerator;
+
+ /* This is easy and makes use of the menus enumeration defined above */
+ enumerator.found = GL_FALSE;
+ enumerator.data = (void *)&menuID;
+ fgEnumMenus( fghcbMenuByID, &enumerator );
+
+ if( enumerator.found )
+ return( SFG_Menu *) enumerator.data;
+
+ return NULL;
+}
+
+/*
+ * A static helper function to look for an active menu
+ */
+static void fghcbGetActiveMenu( SFG_Menu *menu,
+ SFG_Enumerator *enumerator )
+{
+ if ( enumerator->found )
+ return;
+
+ /* Check the menu's is active */
+ if( menu->IsActive )
+ {
+ enumerator->found = GL_TRUE;
+ enumerator->data = menu;
+
+ return;
+ }
+}
+
+/*
+ * Returns active menu, if any. Assumption: only one menu active throughout application at any one time.
+ * This is false when a submenu is also open.
+ * This is easier than fgWindowByXXX as all menus are placed in one doubly linked list...
+ */
+SFG_Menu* fgGetActiveMenu( )
+{
+ SFG_Enumerator enumerator;
+
+ /* This is easy and makes use of the menus enumeration defined above */
+ enumerator.found = GL_FALSE;
+ fgEnumMenus( fghcbGetActiveMenu, &enumerator );
+
+ if( enumerator.found )
+ return( SFG_Menu *) enumerator.data;
- /* It's enough to check all entries in fgStructure.Menus... */
- for( menu = (SFG_Menu *)fgStructure.Menus.First;
- menu;
- menu = (SFG_Menu *)menu->Node.Next )
- if( menu->ID == menuID )
- return menu;
return NULL;
}