]> git.saurik.com Git - wxWidgets.git/blobdiff - src/motif/toolbar.cpp
Implement support for button mnemonics in wxOSX/Cocoa.
[wxWidgets.git] / src / motif / toolbar.cpp
index f62b739ad04f07d0afe70b4d83944ccd22d49007..c8ae30e002ce32112854879f8361e774315b2a32 100644 (file)
@@ -1,5 +1,5 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        motif/toolbar.cpp
+// Name:        src/motif/toolbar.cpp
 // Purpose:     wxToolBar
 // Author:      Julian Smart
 // Modified by: 13.12.99 by VZ during toolbar classes reorganization
 // headers
 // ----------------------------------------------------------------------------
 
-#ifdef __GNUG__
-    #pragma implementation "toolbar.h"
-#endif
-
-#ifdef __VMS
-#define XtDisplay XTDISPLAY
-#endif
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
 
-#include "wx/wx.h"
-#include "wx/app.h"
-#include "wx/timer.h"
 #include "wx/toolbar.h"
 
+#ifndef WX_PRECOMP
+    #include "wx/app.h"
+    #include "wx/frame.h"
+    #include "wx/timer.h"
+    #include "wx/settings.h"
+#endif
+
 #ifdef __VMS__
 #pragma message disable nosimpint
 #endif
 #endif
 
 #include "wx/motif/private.h"
+#include "wx/motif/bmpmotif.h"
 
 // ----------------------------------------------------------------------------
 // wxWin macros
 // ----------------------------------------------------------------------------
 
-#if !USE_SHARED_LIBRARY
-IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxToolBarBase)
-#endif
+IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl)
 
 // ----------------------------------------------------------------------------
 // private functions
@@ -95,8 +93,8 @@ public:
         Init();
     }
 
-    wxToolBarTool(wxToolBar *tbar, wxControl *control)
-        : wxToolBarToolBase(tbar, control)
+    wxToolBarTool(wxToolBar *tbar, wxControl *control, const wxString& label)
+        : wxToolBarToolBase(tbar, control, label)
     {
         Init();
     }
@@ -107,21 +105,29 @@ public:
     void SetWidget(Widget widget) { m_widget = widget; }
     Widget GetButtonWidget() const { return m_widget; }
 
-    void SetPixmap(Pixmap pixmap) { m_pixmap = pixmap; }
-    Pixmap GetPixmap() const { return m_pixmap; }
+    Pixmap GetArmPixmap()
+    {
+        m_bitmapCache.SetBitmap( GetNormalBitmap() );
+        return (Pixmap)m_bitmapCache.GetArmPixmap( (WXWidget)m_widget );
+    }
 
+    Pixmap GetInsensPixmap()
+    {
+        m_bitmapCache.SetBitmap( GetNormalBitmap() );
+        return (Pixmap)m_bitmapCache.GetInsensPixmap( (WXWidget)m_widget );
+    }
 protected:
     void Init();
 
     Widget m_widget;
-    Pixmap m_pixmap;
+    wxBitmapCache m_bitmapCache;
 };
 
 // ----------------------------------------------------------------------------
 // globals
 // ----------------------------------------------------------------------------
 
-static wxToolBarTimer* wxTheToolBarTimer = (wxToolBarTimer*) NULL;
+static wxToolBarTimer* wxTheToolBarTimer = NULL;
 
 Widget wxToolBarTimer::help_popup = (Widget) 0;
 Widget wxToolBarTimer::buttonWidget = (Widget) 0;
@@ -149,24 +155,21 @@ wxToolBarToolBase *wxToolBar::CreateTool(int id,
 }
 
 
-wxToolBarToolBase *wxToolBar::CreateTool(wxControl *control)
+wxToolBarToolBase *
+wxToolBar::CreateTool(wxControl *control, const wxString& label)
 {
-    return new wxToolBarTool(this, control);
+    return new wxToolBarTool(this, control, label);
 }
 
 void wxToolBarTool::Init()
 {
     m_widget = (Widget)0;
-    m_pixmap = (Pixmap)0;
 }
 
 wxToolBarTool::~wxToolBarTool()
 {
     if ( m_widget )
         XtDestroyWidget(m_widget);
-    if ( m_pixmap )
-        XmDestroyPixmap(DefaultScreenOfDisplay((Display*)wxGetDisplay()),
-                        m_pixmap);
 }
 
 // ----------------------------------------------------------------------------
@@ -194,18 +197,12 @@ bool wxToolBar::Create(wxWindow *parent,
                        long style,
                        const wxString& name)
 {
-    Init();
-
-    m_windowId = id;
-
-    SetName(name);
-    m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
-    m_foregroundColour = parent->GetForegroundColour();
-    m_windowStyle = style;
+    if( !wxControl::CreateControl( parent, id, pos, size, style,
+                                   wxDefaultValidator, name ) )
+        return false;
+    PreCreation();
 
-    SetParent(parent);
-
-    if (parent) parent->AddChild(this);
+    FixupStyle();
 
     Widget parentWidget = (Widget) parent->GetClientWidget();
 
@@ -230,21 +227,24 @@ bool wxToolBar::Create(wxWindow *parent,
 
     m_mainWidget = (WXWidget) toolbar;
 
-    m_font = parent->GetFont();
-    ChangeFont(FALSE);
+    wxPoint rPos = pos;
+    wxSize  rSize = size;
 
-    SetCanAddEventHandler(TRUE);
-    AttachWidget (parent, m_mainWidget, (WXWidget) NULL, pos.x, pos.y, size.x, size.y);
+    if( rPos.x == -1 ) rPos.x = 0;
+    if( rPos.y == -1 ) rPos.y = 0;
+    if( rSize.x == -1 && GetParent() )
+        rSize.x = GetParent()->GetSize().x;
 
-    ChangeBackgroundColour();
+    PostCreation();
+    AttachWidget (parent, m_mainWidget, (WXWidget) NULL,
+                  rPos.x, rPos.y, rSize.x, rSize.y);
 
-    return TRUE;
+    return true;
 }
 
 wxToolBar::~wxToolBar()
 {
-    delete wxTheToolBarTimer;
-    wxTheToolBarTimer = NULL;
+    wxDELETE(wxTheToolBarTimer);
 }
 
 bool wxToolBar::Realize()
@@ -252,9 +252,11 @@ bool wxToolBar::Realize()
     if ( m_tools.GetCount() == 0 )
     {
         // nothing to do
-        return TRUE;
+        return true;
     }
 
+    bool isVertical = GetWindowStyle() & wxTB_VERTICAL;
+
     // Separator spacing
     const int separatorSize = GetToolSeparation(); // 8;
     wxSize margins = GetToolMargins();
@@ -265,15 +267,13 @@ bool wxToolBar::Realize()
     int currentX = marginX;
     int currentY = marginY;
 
-    int buttonHeight = 0;
-
-    int currentSpacing = 0;
+    int buttonHeight = 0, buttonWidth = 0;
 
     Widget button;
     Pixmap pixmap, insensPixmap;
-    wxBitmap bmp;
+    wxBitmap bmp, insensBmp;
 
-    wxToolBarToolsList::Node *node = m_tools.GetFirst();
+    wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
     while ( node )
     {
         wxToolBarTool *tool = (wxToolBarTool *)node->GetData();
@@ -285,22 +285,32 @@ bool wxToolBar::Realize()
                 wxControl* control = tool->GetControl();
                 wxSize sz = control->GetSize();
                 wxPoint pos = control->GetPosition();
-                // Allow a control to specify a y-offset by setting its initial position,
-                // but still don't allow it to position itself above the top margin.
-                int controlY = (pos.y > 0) ? currentY + pos.y : currentY;
-                control->Move(currentX, controlY);
-                currentX += sz.x + packing;
+                // Allow a control to specify a y[x]-offset by setting
+                // its initial position, but still don't allow it to
+                // position itself above the top[left] margin.
+                int controlY = (pos.y > 0) ? pos.y : currentY;
+                int controlX = (pos.x > 0) ? pos.x : currentX;
+                control->Move( isVertical ? controlX : currentX,
+                               isVertical ? currentY : controlY );
+                if ( isVertical )
+                    currentY += sz.y + packing;
+                else
+                    currentX += sz.x + packing;
 
                 break;
             }
             case wxTOOL_STYLE_SEPARATOR:
-                currentX += separatorSize;
+                // skip separators for vertical toolbars
+                if( !isVertical )
+                {
+                    currentX += separatorSize;
+                }
                 break;
 
             case wxTOOL_STYLE_BUTTON:
                 button = (Widget) 0;
 
-                if ( tool->CanBeToggled() )
+                if ( tool->CanBeToggled() && !tool->GetButtonWidget() )
                 {
                     button = XtVaCreateWidget("toggleButton",
                             xmToggleButtonWidgetClass, (Widget) m_mainWidget,
@@ -314,14 +324,18 @@ bool wxToolBar::Realize()
                             XmNmultiClick, XmMULTICLICK_KEEP,
                             XmNlabelType, XmPIXMAP,
                             NULL);
-                    XtAddCallback ((Widget) button, XmNvalueChangedCallback, (XtCallbackProc) wxToolButtonCallback,
-                            (XtPointer) this);
+                    XtAddCallback ((Widget) button,
+                                   XmNvalueChangedCallback,
+                                   (XtCallbackProc) wxToolButtonCallback,
+                                   (XtPointer) this);
 
                     XtVaSetValues ((Widget) button,
-                            XmNselectColor, m_backgroundColour.AllocColour(XtDisplay((Widget) button)),
-                            NULL);
+                                   XmNselectColor,
+                                   m_backgroundColour.AllocColour
+                                       (XtDisplay((Widget) button)),
+                                   NULL);
                 }
-                else
+                else if( !tool->GetButtonWidget() )
                 {
                     button = XtVaCreateWidget("button",
                             xmPushButtonWidgetClass, (Widget) m_mainWidget,
@@ -331,94 +345,81 @@ bool wxToolBar::Realize()
                             XmNlabelType, XmPIXMAP,
                             NULL);
                     XtAddCallback (button,
-                            XmNactivateCallback, (XtCallbackProc) wxToolButtonCallback,
-                            (XtPointer) this);
+                                   XmNactivateCallback,
+                                   (XtCallbackProc) wxToolButtonCallback,
+                                   (XtPointer) this);
                 }
 
-                DoChangeBackgroundColour((WXWidget) button, m_backgroundColour, TRUE);
+                if( !tool->GetButtonWidget() )
+                {
+                    wxDoChangeBackgroundColour((WXWidget) button,
+                                               m_backgroundColour, true);
 
-                tool->SetWidget(button);
+                    tool->SetWidget(button);
+                }
+                else
+                {
+                    button = (Widget)tool->GetButtonWidget();
+                    XtVaSetValues( button,
+                                   XmNx, currentX, XmNy, currentY,
+                                   NULL );
+                }
 
                 // For each button, if there is a mask, we must create
                 // a new wxBitmap that has the correct background colour
                 // for the button. Otherwise the background will just be
                 // e.g. black if a transparent XPM has been loaded.
                 bmp = tool->GetNormalBitmap();
-                if ( bmp.GetMask() )
+                insensBmp = tool->GetDisabledBitmap();
+                if ( bmp.GetMask() || insensBmp.GetMask() )
                 {
-                    int backgroundPixel;
+                    WXPixel backgroundPixel;
                     XtVaGetValues(button, XmNbackground, &backgroundPixel,
-                            NULL);
+                                  NULL);
 
                     wxColour col;
                     col.SetPixel(backgroundPixel);
 
-                    bmp = wxCreateMaskedBitmap(bmp, col);
+                    if( bmp.IsOk() && bmp.GetMask() )
+                    {
+                        bmp = wxCreateMaskedBitmap(bmp, col);
+                        tool->SetNormalBitmap(bmp);
+                    }
 
-                    tool->SetNormalBitmap(bmp);
+                    if( insensBmp.IsOk() && insensBmp.GetMask() )
+                    {
+                        insensBmp = wxCreateMaskedBitmap(insensBmp, col);
+                        tool->SetDisabledBitmap(insensBmp);
+                    }
                 }
 
                 // Create a selected/toggled bitmap. If there isn't a 2nd
                 // bitmap, we need to create it (with a darker, selected
                 // background)
-                int backgroundPixel;
+                WXPixel backgroundPixel;
                 if ( tool->CanBeToggled() )
                     XtVaGetValues(button, XmNselectColor, &backgroundPixel,
-                            NULL);
+                                  NULL);
                 else
                     XtVaGetValues(button, XmNarmColor, &backgroundPixel,
-                            NULL);
-
+                                  NULL);
                 wxColour col;
                 col.SetPixel(backgroundPixel);
 
-                // FIXME: we use disabled bitmap as the bitmap for the toggled
-                //        state, we probably need a GetToggledBitmap() instead
-                wxBitmap bmpToggled = tool->GetDisabledBitmap();
-                if ( bmpToggled.Ok() && bmpToggled.GetMask())
+                pixmap = (Pixmap) bmp.GetDrawable();
                 {
-                    // Use what's there
-                    wxBitmap newBitmap = wxCreateMaskedBitmap(bmpToggled, col);
-                    tool->SetDisabledBitmap(newBitmap);
-                }
-                else
-                {
-                    // Use unselected bitmap
-                    if ( bmp.GetMask() )
-                    {
-                        wxBitmap newBitmap = wxCreateMaskedBitmap(bmp, col);
-                        tool->SetDisabledBitmap(newBitmap);
-                    }
-                    else
-                        tool->SetDisabledBitmap(bmp);
-                }
+                    wxBitmap tmp = tool->GetDisabledBitmap();
 
-                // FIXME: and here we should use GetDisabledBitmap()...
-                pixmap = (Pixmap) bmp.GetPixmap();
-                insensPixmap = (Pixmap) bmp.GetInsensPixmap();
+                    insensPixmap = tmp.IsOk() ?
+                            (Pixmap)tmp.GetDrawable() :
+                            tool->GetInsensPixmap();
+                }
 
                 if (tool->CanBeToggled())
                 {
                     // Toggle button
-                    Pixmap pixmap2 = (Pixmap) 0;
-                    Pixmap insensPixmap2 = (Pixmap) 0;
-
-                    // If there's a bitmap for the toggled state, use it,
-                    // otherwise generate one.
-                    //
-                    // FIXME: see above
-                    if ( bmpToggled.Ok() )
-                    {
-                        pixmap2 = (Pixmap) bmpToggled.GetPixmap();
-                        insensPixmap2 = (Pixmap) bmpToggled.GetInsensPixmap();
-                    }
-                    else
-                    {
-                        pixmap2 = (Pixmap) bmp.GetArmPixmap(button);
-                        insensPixmap2 = XCreateInsensitivePixmap((Display*) wxGetDisplay(), pixmap2);
-                    }
-
-                    tool->SetPixmap(pixmap2);
+                    Pixmap pixmap2 = tool->GetArmPixmap();
+                    Pixmap insensPixmap2 = tool->GetInsensPixmap();
 
                     XtVaSetValues (button,
                             XmNfillOnSelect, True,
@@ -431,21 +432,7 @@ bool wxToolBar::Realize()
                 }
                 else
                 {
-                    Pixmap pixmap2 = (Pixmap) 0;
-
-                    // If there's a bitmap for the armed state, use it,
-                    // otherwise generate one.
-                    if ( bmpToggled.Ok() )
-                    {
-                        pixmap2 = (Pixmap) bmpToggled.GetPixmap();
-                    }
-                    else
-                    {
-                        pixmap2 = (Pixmap) bmp.GetArmPixmap(button);
-
-                    }
-
-                    tool->SetPixmap(pixmap2);
+                    Pixmap pixmap2 = tool->GetArmPixmap();
 
                     // Normal button
                     XtVaSetValues(button,
@@ -463,52 +450,142 @@ bool wxToolBar::Realize()
                                   XmNwidth, &width,
                                   XmNheight, & height,
                                   NULL);
-                    currentX += width + packing;
+                    if ( isVertical )
+                        currentY += height + packing;
+                    else
+                        currentX += width + packing;
                     buttonHeight = wxMax(buttonHeight, height);
+                    buttonWidth = wxMax(buttonWidth, width);
                 }
 
                 XtAddEventHandler (button, EnterWindowMask | LeaveWindowMask,
                         False, wxToolButtonPopupCallback, (XtPointer) this);
 
-                currentSpacing = 0;
                 break;
         }
 
         node = node->GetNext();
     }
 
-    SetSize(-1, -1, currentX, buttonHeight + 2*marginY);
+    SetSize( -1, -1,
+             isVertical ? buttonWidth + 2 * marginX : -1,
+             isVertical ? -1 : buttonHeight +  2*marginY );
 
-    return TRUE;
+    return true;
 }
 
 wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord WXUNUSED(x),
                                                   wxCoord WXUNUSED(y)) const
 {
-    wxFAIL_MSG( _T("TODO") );
+    wxFAIL_MSG( wxT("TODO") );
 
-    return (wxToolBarToolBase *)NULL;
+    return NULL;
 }
 
 bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos), wxToolBarToolBase *tool)
 {
     tool->Attach(this);
 
-    return TRUE;
+    return true;
 }
 
 bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos), wxToolBarToolBase *tool)
 {
     tool->Detach();
 
-    return TRUE;
+    bool isVertical = GetWindowStyle() & wxTB_VERTICAL;
+    const int separatorSize = GetToolSeparation(); // 8;
+    int packing = GetToolPacking();
+    int offset = 0;
+
+    for( wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
+         node; node = node->GetNext() )
+    {
+        wxToolBarTool *t = (wxToolBarTool*)node->GetData();
+
+        if( t == tool )
+        {
+            switch ( t->GetStyle() )
+            {
+            case wxTOOL_STYLE_CONTROL:
+            {
+                wxSize size = t->GetControl()->GetSize();
+                offset = isVertical ? size.y : size.x;
+                offset += packing;
+                break;
+            }
+            case wxTOOL_STYLE_SEPARATOR:
+                offset = isVertical ? 0 : separatorSize;
+                break;
+            case wxTOOL_STYLE_BUTTON:
+            {
+                Widget w = t->GetButtonWidget();
+                Dimension width, height;
+
+                XtVaGetValues( w,
+                               XmNwidth, &width,
+                               XmNheight, &height,
+                               NULL );
+
+                offset = isVertical ? height : width;
+                offset += packing;
+                break;
+            }
+            }
+        }
+        else if( offset )
+        {
+            switch ( t->GetStyle() )
+            {
+            case wxTOOL_STYLE_CONTROL:
+            {
+                wxPoint location = t->GetControl()->GetPosition();
+
+                if( isVertical )
+                    location.y -= offset;
+                else
+                    location.x -= offset;
+
+                t->GetControl()->Move( location );
+                break;
+            }
+            case wxTOOL_STYLE_SEPARATOR:
+                break;
+            case wxTOOL_STYLE_BUTTON:
+            {
+                Dimension x, y;
+                XtVaGetValues( t->GetButtonWidget(),
+                               XmNx, &x,
+                               XmNy, &y,
+                               NULL );
+
+                if( isVertical )
+                    y = (Dimension)(y - offset);
+                else
+                    x = (Dimension)(x - offset);
+
+                XtVaSetValues( t->GetButtonWidget(),
+                               XmNx, x,
+                               XmNy, y,
+                               NULL );
+                break;
+            }
+            }
+        }
+    }
+
+    return true;
 }
 
 void wxToolBar::DoEnableTool(wxToolBarToolBase *toolBase, bool enable)
 {
     wxToolBarTool *tool = (wxToolBarTool *)toolBase;
-
-    XtSetSensitive(tool->GetButtonWidget(), (Boolean) enable);
+    if (tool->GetButtonWidget()){
+        XtSetSensitive(tool->GetButtonWidget(), (Boolean) enable);
+    } else if (wxTOOL_STYLE_CONTROL == tool->GetStyle()){
+        // Controls (such as wxChoice) do not have button widgets
+        tool->GetControl()->Enable(enable);
+    }
 }
 
 void wxToolBar::DoToggleTool(wxToolBarToolBase *toolBase, bool toggle)
@@ -524,13 +601,45 @@ void wxToolBar::DoSetToggle(wxToolBarToolBase * WXUNUSED(tool),
     // nothing to do
 }
 
+void wxToolBar::DoSetSize(int x, int y, int width, int height, int sizeFlags)
+{
+    int old_width, old_height;
+    GetSize(&old_width, &old_height);
+
+    // Correct width and height if needed.
+    if ( width == -1 || height == -1 )
+    {
+        wxSize defaultSize = GetSize();
+
+        if ( width == -1 )
+            width = defaultSize.x;
+        if ( height == -1 )
+            height = defaultSize.y;
+    }
+
+    wxToolBarBase::DoSetSize(x, y, width, height, sizeFlags);
+
+    // We must refresh the frame size when the toolbar changes size
+    // otherwise the toolbar can be shown incorrectly
+    if ( old_width != width || old_height != height )
+    {
+        // But before we send the size event check it
+        // we have a frame that is not being deleted.
+        wxFrame *frame = wxDynamicCast(GetParent(), wxFrame);
+        if ( frame && !frame->IsBeingDeleted() )
+        {
+            frame->SendSizeEvent();
+        }
+    }
+}
+
 // ----------------------------------------------------------------------------
 // Motif callbacks
 // ----------------------------------------------------------------------------
 
 wxToolBarToolBase *wxToolBar::FindToolByWidget(WXWidget w) const
 {
-    wxToolBarToolsList::Node* node = m_tools.GetFirst();
+    wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
     while ( node )
     {
         wxToolBarTool *tool = (wxToolBarTool *)node->GetData();
@@ -542,7 +651,7 @@ wxToolBarToolBase *wxToolBar::FindToolByWidget(WXWidget w) const
         node = node->GetNext();
     }
 
-    return (wxToolBarToolBase *)NULL;
+    return NULL;
 }
 
 static void wxToolButtonCallback(Widget w,
@@ -602,7 +711,7 @@ static void wxToolButtonPopupCallback(Widget w,
         wxToolBarTimer::help_popup = (Widget) 0;
 
         // One shot
-        wxTheToolBarTimer->Start(delayMilli, TRUE);
+        wxTheToolBarTimer->Start(delayMilli, true);
 
     }
     /************************************************************/
@@ -642,7 +751,7 @@ void wxToolBarTimer::Notify()
 
         // Move the tooltip more or less above the button
         int yOffset = 20; // TODO: What should be really?
-        y -= yOffset;
+        y = (Position)(y - yOffset);
         if (y < yOffset) y = 0;
 
         /************************************************************/
@@ -674,4 +783,3 @@ void wxToolBarTimer::Notify()
         /************************************************************/
         XtPopup (help_popup, XtGrabNone);
 }
-