]> git.saurik.com Git - wxWidgets.git/blobdiff - src/palmos/menu.cpp
fixed TLWs resizing to invalidate the DFB surface used for painting
[wxWidgets.git] / src / palmos / menu.cpp
index e5177ca4daf21c54b6feec5adf0c1455b6761fb2..727475792103bc3166e0ba14cd60a897758a9725 100644 (file)
@@ -1,10 +1,10 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        menu.cpp
+// Name:        src/palmos/menu.cpp
 // Purpose:     wxMenu, wxMenuBar, wxMenuItem
-// Author:      William Osborne
+// Author:      William Osborne - minimal working wxPalmOS port
 // Modified by:
 // Created:     10/12/04
-// RCS-ID:      $Id
+// RCS-ID:      $Id$
 // Copyright:   (c) William Osborne
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 // headers
 // ---------------------------------------------------------------------------
 
-#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
-    #pragma implementation "menu.h"
-#endif
-
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
 
 #if wxUSE_MENUS
 
+#include "wx/menu.h"
+
 #ifndef WX_PRECOMP
     #include "wx/frame.h"
-    #include "wx/menu.h"
     #include "wx/utils.h"
     #include "wx/intl.h"
     #include "wx/log.h"
     #include "wx/ownerdrw.h"
 #endif
 
-// other standard headers
-#include <string.h>
-
-#ifdef __PALMOS__
-    #include <PalmOS.h>
-    #include <Menu.h>
-#endif
+#include <Loader.h>
+#include <Form.h>
+#include <Menu.h>
 
 // ----------------------------------------------------------------------------
 // global variables
@@ -71,9 +64,9 @@ static const int idMenuTitle = -3;
 // implementation
 // ============================================================================
 
-#include <wx/listimpl.cpp>
+#include "wx/listimpl.cpp"
 
-WX_DEFINE_LIST( wxMenuInfoList ) ;
+WX_DEFINE_LIST( wxMenuInfoList )
 
 #if wxUSE_EXTENDED_RTTI
 
@@ -128,7 +121,7 @@ wxEND_PROPERTIES_TABLE()
 wxBEGIN_HANDLERS_TABLE(wxMenuInfo)
 wxEND_HANDLERS_TABLE()
 
-wxCONSTRUCTOR_2( wxMenuInfo , wxMenu* , Menu , wxString , Title ) 
+wxCONSTRUCTOR_2( wxMenuInfo , wxMenu* , Menu , wxString , Title )
 
 wxCOLLECTION_TYPE_INFO( wxMenuInfo * , wxMenuInfoList ) ;
 
@@ -206,11 +199,11 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
 {
     if ( IsAttached() && GetMenuBar()->IsAttached() )
     {
-           // Regenerate the menu resource        
+        // Regenerate the menu resource
         GetMenuBar()->Refresh();
     }
-    
-    return TRUE;
+
+    return true;
 }
 
 void wxMenu::EndRadioGroup()
@@ -227,11 +220,11 @@ wxMenuItem* wxMenu::DoAppend(wxMenuItem *item)
     }
     else if(IsAttached() && GetMenuBar()->IsAttached())
     {
-           // Regenerate the menu resource        
+        // Regenerate the menu resource
         GetMenuBar()->Refresh();
     }
-    
-    return item;    
+
+    return item;
 }
 
 wxMenuItem* wxMenu::DoInsert(size_t pos, wxMenuItem *item)
@@ -239,7 +232,7 @@ wxMenuItem* wxMenu::DoInsert(size_t pos, wxMenuItem *item)
     if (wxMenuBase::DoInsert(pos, item) && DoInsertOrAppend(item, pos))
         return item;
     else
-        return NULL;    
+        return NULL;
 }
 
 wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
@@ -260,13 +253,13 @@ wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
 
     // remove the item from the menu
     wxMenuItem *ret=wxMenuBase::DoRemove(item);
-    
+
     if ( IsAttached() && GetMenuBar()->IsAttached() )
     {
-           // Regenerate the menu resource        
+        // Regenerate the menu resource
         GetMenuBar()->Refresh();
     }
-    
+
     return ret;
 }
 
@@ -301,7 +294,7 @@ void wxMenu::SetTitle(const wxString& label)
 
     if ( IsAttached() && GetMenuBar()->IsAttached() )
     {
-           // Regenerate the menu resource        
+        // Regenerate the menu resource
         GetMenuBar()->Refresh();
     }
 }
@@ -340,7 +333,7 @@ wxMenuBar::wxMenuBar( long WXUNUSED(style) )
 {
 }
 
-wxMenuBar::wxMenuBar(int count, wxMenu *menus[], const wxString titles[])
+wxMenuBar::wxMenuBar(size_t count, wxMenu *menus[], const wxString titles[], long WXUNUSED(style))
 {
 }
 
@@ -426,7 +419,7 @@ wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
 bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
 {
     if ( !wxMenuBarBase::Insert(pos, menu, title) )
-        return FALSE;
+        return false;
 
     m_titles.Insert(wxStripMenuCodes(title), pos);
 
@@ -436,13 +429,13 @@ bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
         Refresh();
     }
 
-    return TRUE;
+    return true;
 }
 
 bool wxMenuBar::Append(wxMenu *menu, const wxString& title)
 {
     if ( !wxMenuBarBase::Append(menu, title) )
-        return FALSE;
+        return false;
 
     m_titles.Add(wxStripMenuCodes(title));
 
@@ -452,7 +445,7 @@ bool wxMenuBar::Append(wxMenu *menu, const wxString& title)
         Refresh();
     }
 
-    return TRUE;    
+    return true;
 }
 
 wxMenu *wxMenuBar::Remove(size_t pos)
@@ -484,17 +477,17 @@ int wxMenuBar::ProcessCommand(int ItemID)
 {
     if(!IsAttached())
         return -1;
-        
+
     int MenuNum=(ItemID/1000)-1;
     int ItemNum=(ItemID-(1000*(MenuNum+1)));
-    
+
     // Should never happen, but it doesn't hurt to check anyway.
     if(MenuNum>GetMenuCount())
         return -1;
 
     // Get the menu
     wxMenu *ActiveMenu=GetMenu(MenuNum);
-    
+
     // Make sure this is a valid item.
     if(ItemNum>ActiveMenu->GetMenuItemCount())
         return -1;
@@ -506,45 +499,45 @@ int wxMenuBar::ProcessCommand(int ItemID)
     return ActiveID;
 }
 
-/* Palm OS does not have good dynamic menu support.  About all you can do with 
- * the standard API calls is to add new items to an existing drop-down menu and 
- * hide/show items in a drop-down menu.  It is impossible to add, hide, or 
- * change the label on a drop-down menu. 
- * 
- * The easiest and simplest way around this limitation is to modify the Palm OS 
- * MenuBarType structure directly.  This gives limited ability to change the 
- * label on a drop-down menu.  I have not been able to find a safe way to add, 
+/* Palm OS does not have good dynamic menu support.  About all you can do with
+ * the standard API calls is to add new items to an existing drop-down menu and
+ * hide/show items in a drop-down menu.  It is impossible to add, hide, or
+ * change the label on a drop-down menu.
+ *
+ * The easiest and simplest way around this limitation is to modify the Palm OS
+ * MenuBarType structure directly.  This gives limited ability to change the
+ * label on a drop-down menu.  I have not been able to find a safe way to add,
  * delete, or resize drop-down menus in OS 6.
- * 
+ *
  * The following routine attempt to work around these limitations present in the
- * Palm OS API to provide limited dynamic menu support.  This solution is far 
+ * Palm OS API to provide limited dynamic menu support.  This solution is far
  * from perfect, but the only other option is to wait for PalmSource to add full
  * dynamic menu support, or to recreate the Palm OS menu system from scratch.
- * 
+ *
  * This system is limited in that no more than 4 drop-down menus are allowed per
  * menu bar, and the label for each drop-down menu is limited to 8 characters of
  * text.  However, this menu system should work for most applications.
- * 
- * Basically the menu routines select one of four menu bars, depending on 
- * whether or not the requested menu bar has one, two, three, or four drop-down 
+ *
+ * Basically the menu routines select one of four menu bars, depending on
+ * whether or not the requested menu bar has one, two, three, or four drop-down
  * menus.
- * 
- * These four "template" menu bars contain one, two, three, or four drop-down 
- * menus.  Each menu has a dummy menu item attached to it to allow the Palm OS 
+ *
+ * These four "template" menu bars contain one, two, three, or four drop-down
+ * menus.  Each menu has a dummy menu item attached to it to allow the Palm OS
  * MenuAddItem function to add the real items.
- * 
- * The labels on the drop-down menus are then replaced with the labels of the 
+ *
+ * The labels on the drop-down menus are then replaced with the labels of the
  * real menus.
- * 
- * The menu is then attached to the active window and the MenuAddItem API 
- * function is called to add the items to each drop-down menu.  Finally, 
+ *
+ * The menu is then attached to the active window and the MenuAddItem API
+ * function is called to add the items to each drop-down menu.  Finally,
  * MenuHideItem is called to remove the dummy items from each drop-down menu.
  */
 void wxMenuBar::LoadMenu()
 {
     int i=0;
     int j=0;
-    
+
     // Handle to the currently running application database
     DmOpenRef    AppDB;
 
@@ -555,16 +548,16 @@ void wxMenuBar::LoadMenu()
     int NumMenus=GetMenuCount();
 
     // Set up the pointers and handles
-    char *PalmOSMenuBarPtr;    
+    char *PalmOSMenuBarPtr;
     MemHandle PalmOSMenuBar;
-            
+
     // Load the menu template and set up the menu pointers
     if(NumMenus==1)
     {
         PalmOSMenuBar=DmGetResource(AppDB,'MBAR',1000);
         PalmOSMenuBarPtr=(char *)MemHandleLock(PalmOSMenuBar);
 
-        PalmOSMenuBarPtr+=74;    
+        PalmOSMenuBarPtr+=74;
     }
     else if(NumMenus==2)
     {
@@ -582,7 +575,7 @@ void wxMenuBar::LoadMenu()
     }
     else
     {
-        // We support a maximum of 4 menus, so make sure that do not create 
+        // We support a maximum of 4 menus, so make sure that do not create
         // more than we can handle.
         NumMenus=4;
 
@@ -591,14 +584,14 @@ void wxMenuBar::LoadMenu()
 
         PalmOSMenuBarPtr+=200;
     }
-    
+
     // Set the proper names for the drop-down triggers.
     for(i=0;i<NumMenus;i++)
     {
         // Clear out the old label
         char buffer[8]={' ',' ',' ',' ',' ',' ',' ',' '};
         MemMove(PalmOSMenuBarPtr,buffer,8);
-        
+
         wxString MenuTitle=m_titles.Item(i);
 
         // Make sure we don't copy more than 8 bytes for the label
@@ -611,28 +604,28 @@ void wxMenuBar::LoadMenu()
     }
 
     // We are done with the menu pointer.
-    MemHandleUnlock(PalmOSMenuBar);    
+    MemHandleUnlock(PalmOSMenuBar);
     DmReleaseResource(PalmOSMenuBar);
 
-    // We must make the menu active before we can add items to the drop-down 
+    // We must make the menu active before we can add items to the drop-down
     // triggers.
     FrmSetMenu(FrmGetActiveForm(),AppDB,NumMenus*1000);
 
-    /* Add the menu items to the drop-down triggers.  This must be done after 
-     * setting the triggers, because setting the names of drop-down triggers 
-     * that have a variable number of items requires carefull calculation of 
+    /* Add the menu items to the drop-down triggers.  This must be done after
+     * setting the triggers, because setting the names of drop-down triggers
+     * that have a variable number of items requires carefull calculation of
      * the offsets in the MenuBarType structure.  Setting the triggers first
      * avoids this.
      */
     for(i=0;i<NumMenus;i++)
     {
         wxMenu *CurrentMenu=GetMenu(i);
-        
+
         for(j=0;j<CurrentMenu->GetMenuItemCount();j++)
         {
             wxMenuItem *CurrentItem=CurrentMenu->FindItemByPosition(j);
             wxString ItemLabel=CurrentItem->GetLabel();
-            
+
             if(CurrentItem->IsSeparator()==true)
             {
                 char Separator=MenuSeparatorChar;
@@ -649,7 +642,7 @@ void wxMenuBar::LoadMenu()
                     MenuAddItem(((i*1000)+1000)+j-1,((i*1000)+1000)+j,0x00,ItemLabel);
             }
         }
-        
+
         // Hide the dummy menu item, since we don't need it anymore.
         MenuHideItem(9000+i);
     }
@@ -657,17 +650,93 @@ void wxMenuBar::LoadMenu()
 
 void wxMenuBar::Attach(wxFrame *frame)
 {
+    // before attaching preprocess menus to not include wxID_EXIT item
+    // as PalmOS guidelines suggest
+
+    wxMenuItem *item;
+    wxMenu *menu;
+    int i;
+
+    while( item = FindItem(wxID_EXIT) )
+    {
+        menu = item->GetMenu();
+        if( !menu ) break; // something broken ?
+
+        size_t count = menu->GetMenuItemCount();
+        if( count == 0 ) break; // something broken ?
+
+        // if EXIT is last item in menu
+        if( menu->FindItemByPosition( count - 1 ) == item )
+        {
+            menu->Destroy( item );
+
+            // was more than one item?
+            // was previous separator ?
+            if( count > 2 )
+            {
+                item = menu->FindItemByPosition( count - 2 );
+                if(item && item->IsSeparator())
+                    menu->Destroy( item );
+            }
+        }
+
+        // if EXIT is first item in menu
+        else if( menu->FindItemByPosition( 0 ) == item )
+        {
+            menu->Destroy( item );
+
+            // was more than one item?
+            // was previous separator ?
+            if( count > 2 )
+            {
+                item = menu->FindItemByPosition( 0 );
+                if(item && item->IsSeparator())
+                    menu->Destroy( item );
+            }
+        }
+
+        // if EXIT is in the middle but before and after are selectors
+        else
+        {
+            i = 1; // 0 case already done
+            while ( (i < count) && (menu->FindItemByPosition( 0 ) != item) )
+            {
+                i++;
+            }
+
+            if (i >= count) break;
+            if (menu->FindItemByPosition( i ) != item) break;
+            menu->Destroy( item );
+            item = menu->FindItemByPosition( i );
+            if ( item &&
+                 item->IsSeparator() &&
+                 menu->FindItemByPosition( i-1 )->IsSeparator() )
+            {
+                // noe need for two neighbouring separators
+                menu->Destroy( item );
+            }
+        }
+    }
+
+    // check if we received any empty menu!
+    i = 0;
+    while(i < GetMenuCount())
+    {
+        menu = GetMenu(i);
+
+        if( menu && (menu->GetMenuItemCount()==0) )
+        {
+            menu = Remove( i );
+            delete menu;
+        }
+        else
+            i++;
+    }
+
     wxMenuBarBase::Attach(frame);
-    
-    LoadMenu();
-}
 
-#if defined(__WXWINCE__) && (_WIN32_WCE >= 400 && !defined(__POCKETPC__) && !defined(__SMARTPHONE__))
-bool wxMenuBar::AddAdornments(long style)
-{
-    return false;
+    LoadMenu();
 }
-#endif
 
 void wxMenuBar::Detach()
 {