]> git.saurik.com Git - wxWidgets.git/blobdiff - src/motif/window.cpp
Accelerators implemented for wxMotif; some wxComboBox stupidities cured
[wxWidgets.git] / src / motif / window.cpp
index e0d7b1fec2e749d905dad457997d75552ddca045..dc47a226d6a8d78db4a1020e03e8cd4188417782 100644 (file)
@@ -52,7 +52,7 @@ void wxCanvasRepaintProc (Widget, XtPointer, XmDrawingAreaCallbackStruct * cbs);
 void wxCanvasInputEvent (Widget drawingArea, XtPointer data, XmDrawingAreaCallbackStruct * cbs);
 void wxCanvasMotionEvent (Widget, XButtonEvent * event);
 void wxCanvasEnterLeave (Widget drawingArea, XtPointer clientData, XCrossingEvent * event);
-void wxScrollBarCallback(Widget widget, XtPointer clientData,
+static void wxScrollBarCallback(Widget widget, XtPointer clientData,
                         XmScaleCallbackStruct *cbs);
 void wxPanelItemEventHandler (Widget    wid,
                               XtPointer client_data,
@@ -108,6 +108,8 @@ wxWindow::wxWindow()
 #if  wxUSE_DRAG_AND_DROP
     m_pDropTarget = NULL;
 #endif
+    m_clientObject = (wxClientData*) NULL;
+    m_clientData = NULL;
 
     /// Motif-specific
     m_mainWidget = (WXWidget) 0;
@@ -133,7 +135,6 @@ wxWindow::wxWindow()
     m_canAddEventHandler = FALSE;
     m_scrollPosX = 0;
     m_scrollPosY = 0;
-    m_paintRegion = (WXRegion) 0;
 }
 
 // Destructor
@@ -141,10 +142,6 @@ wxWindow::~wxWindow()
 {
     //// Motif-specific
 
-    if (m_paintRegion)
-        XDestroyRegion ((Region) m_paintRegion);
-    m_paintRegion = (WXRegion) 0;
-
     if (GetMainWidget())
         DetachWidget(GetMainWidget()); // Removes event handlers
 
@@ -239,8 +236,10 @@ wxWindow::~wxWindow()
     // dangling pointers.
     wxPendingDelete.DeleteObject(this);
 
-    if ( m_windowValidator )
-           delete m_windowValidator;
+    if ( m_windowValidator ) delete m_windowValidator;
+    if (m_clientObject) delete m_clientObject;
+
+    ClearUpdateRects();
 }
 
 // Destroy the window (delayed, if a managed window)
@@ -282,6 +281,8 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id,
     m_maxSizeY = -1;
     m_defaultItem = NULL;
     m_windowParent = NULL;
+    m_clientObject = (wxClientData*) NULL;
+    m_clientData = NULL;
 
     // Motif-specific
     m_canAddEventHandler = FALSE;
@@ -305,7 +306,6 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id,
     m_pixmapOffsetY = 0;
     m_scrollPosX = 0;
     m_scrollPosY = 0;
-    m_paintRegion = (WXRegion) 0;
 
     if (!parent)
         return FALSE;
@@ -740,6 +740,8 @@ bool wxWindow::Show(bool show)
     {
        if (m_borderWidget || m_scrolledWindow)
        {
+           if (m_drawingArea)
+             XtMapWidget((Widget) m_drawingArea);
            XtMapWidget(m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow);
        }
        else
@@ -751,6 +753,8 @@ bool wxWindow::Show(bool show)
     {
        if (m_borderWidget || m_scrolledWindow)
        {
+           if (m_drawingArea)
+             XtUnmapWidget((Widget) m_drawingArea);
            XtUnmapWidget(m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow);
        }
        else
@@ -1387,7 +1391,18 @@ void wxWindow::RemoveChild(wxWindow *child)
 
 void wxWindow::DestroyChildren()
 {
-  if (GetChildren()) {
+  if (GetChildren())
+  {
+    wxNode *node = GetChildren()->First();
+    while (node)
+    {
+      wxNode* next = node->Next();
+      wxWindow* child = (wxWindow*) node->Data();
+      delete child;
+      node = next;
+    }
+    GetChildren()->Clear();
+#if 0
     wxNode *node;
     while ((node = GetChildren()->First()) != (wxNode *)NULL) {
       wxWindow *child;
@@ -1397,6 +1412,7 @@ void wxWindow::DestroyChildren()
                        delete node;
       }
     } /* while */
+#endif
   }
 }
 
@@ -1913,6 +1929,27 @@ void wxWindow::SetValidator(const wxValidator& validator)
                m_windowValidator->SetWindow(this) ;
 }
 
+void wxWindow::SetClientObject( wxClientData *data )
+{
+  if (m_clientObject) delete m_clientObject;
+  m_clientObject = data;
+}
+
+wxClientData *wxWindow::GetClientObject()
+{
+  return m_clientObject;
+}
+
+void wxWindow::SetClientData( void *data )
+{
+  m_clientData = data;
+}
+
+void *wxWindow::GetClientData()
+{
+  return m_clientData;
+}
+
 // Find a window by id or name
 wxWindow *wxWindow::FindWindow(long id)
 {
@@ -1975,9 +2012,9 @@ bool wxWindow::AcceptsFocus() const
 }
 
 // Update region access
-wxRegion wxWindow::GetUpdateRegion() const
+wxRegion& wxWindow::GetUpdateRegion() const
 {
-    return m_updateRegion;
+    return (wxRegion&) m_updateRegion;
 }
 
 bool wxWindow::IsExposed(int x, int y, int w, int h) const
@@ -2032,9 +2069,7 @@ void wxWidgetResizeProc(Widget w, XConfigureEvent *event, String args[], int *nu
 bool wxAddWindowToTable(Widget w, wxWindow *win)
 {
   wxWindow *oldItem = NULL;
-#if DEBUG
 //  printf("Adding widget %ld, name = %s\n", w, win->GetClassInfo()->GetClassName());
-#endif
   if ((oldItem = (wxWindow *)wxWidgetHashTable->Get ((long) w)))
   {
     char buf[300];
@@ -2096,75 +2131,41 @@ void wxCanvasRepaintProc (Widget drawingArea, XtPointer clientData,
  XmDrawingAreaCallbackStruct * cbs)
 {
     if (!wxWidgetHashTable->Get ((long) (Widget) drawingArea))
-       return;
+           return;
 
     XEvent * event = cbs->event;
-    wxWindow * canvas = (wxWindow *) clientData;
-    Display * display = (Display *) canvas->GetXDisplay();
-    //    GC gc = (GC) canvas->GetDC()->gc;
+    wxWindow * win = (wxWindow *) clientData;
+    Display * display = (Display *) win->GetXDisplay();
 
     switch (event->type)
     {
-      case Expose:
-      {
-       /* TODO
-        wxCanvasDC* canvasDC = canvas->GetDC();
-        if (canvasDC)
-       {
-          if (canvasDC->onpaint_reg)
-            XDestroyRegion(canvasDC->onpaint_reg);
-          canvasDC->onpaint_reg = XCreateRegion();
-          
-       }
-       */
-
-       int n = canvas->m_updateRects.Number();
-        XRectangle* xrects = new XRectangle[n];
-        int i;
-       for (i = 0; i < canvas->m_updateRects.Number(); i++)
-       {
-         wxRect* rect = (wxRect*) canvas->m_updateRects.Nth(i)->Data();
-         xrects[i].x = rect->x;
-          xrects[i].y = rect->y;
-          xrects[i].width = rect->width;
-          xrects[i].height = rect->height;
-         /* TODO (?) Actually ignore it I think.
-          if (canvasDC)
-            XUnionRectWithRegion(&(xrects[i]), canvasDC->onpaint_reg,
-              canvasDC->onpaint_reg);
-      */
-       }
-       /* TODO must clip the area being repainted. So we need a gc.
-         * Alternatively, wxPaintDC must do the clipping
-         * when it's created.
-        XSetClipRectangles(display, gc, 0, 0, xrects, n, Unsorted);
-       */
-
-        canvas->DoPaint() ; // xrects, n);
-        delete[] xrects;
+        case Expose:
+        {
+            wxRect* rect = new wxRect(event->xexpose.x, event->xexpose.y,
+                                       event->xexpose.width, event->xexpose.height);
+           /*
+            cout << "Expose proc. wxRect: " << rect->x << ", " << rect->y << ", ";
+            cout << rect->width << ", " << rect->height << "\n\n";
+           */
 
-        canvas->m_updateRects.Clear();
+            win->m_updateRects.Append((wxObject*) rect);
 
-       /*
-        if (canvasDC)
-       {
-          XDestroyRegion(canvasDC->onpaint_reg);
-          canvasDC->onpaint_reg = NULL;
-       }
-
-       XGCValues gc_val;
-       gc_val.clip_mask = None;
-       XChangeGC(display, gc, GCClipMask, &gc_val);
-       */
+            if (event -> xexpose.count == 0)
+            {
+                wxPaintEvent event(win->GetId());
+                event.SetEventObject(win);
+                win->GetEventHandler()->ProcessEvent(event);
 
-       break;
-    }
-    default:
-    {
-       cout << "\n\nNew Event ! is = " << event -> type << "\n";
-       break;
+                win->ClearUpdateRects();
+            }
+            break;
+        }
+        default:
+        {
+               cout << "\n\nNew Event ! is = " << event -> type << "\n";
+               break;
+        }
     }
-  }
 }
 
 // Unable to deal with Enter/Leave without a separate EventHandler (Motif 1.1.4)
@@ -2734,7 +2735,7 @@ void wxPanelItemEventHandler (Widget    wid,
   *continueToDispatch = True;
 }
 
-void wxScrollBarCallback(Widget scrollbar, XtPointer clientData,
+static void wxScrollBarCallback(Widget scrollbar, XtPointer clientData,
                         XmScaleCallbackStruct *cbs)
 {
     Widget scrolledWindow = XtParent (scrollbar);
@@ -3024,8 +3025,6 @@ void wxWindow::ChangeForegroundColour()
 
 // Change a widget's foreground and background colours.
 
-// TODO: make this 2 functions, ChangeForegroundColour and ChangeBackgroundColour.
-
 void wxWindow::DoChangeForegroundColour(WXWidget widget, wxColour& foregroundColour)
 {
   // When should we specify the foreground, if it's calculated
@@ -3072,12 +3071,11 @@ void wxWindow::SetForegroundColour(const wxColour& col)
     ChangeForegroundColour();
 }
 
-void wxWindow::ChangeFont()
+void wxWindow::ChangeFont(bool keepOriginalSize)
 {
     // Note that this causes the widget to be resized back
     // to its original size! We therefore have to set the size
     // back again. TODO: a better way in Motif?
-    /*
     Widget w = (Widget) GetLabelWidget(); // Usually the main widget
     if (w && m_windowFont.Ok())
     {
@@ -3089,12 +3087,11 @@ void wxWindow::ChangeFont()
                   NULL);
 
         GetSize(& width1, & height1);
-        if (width != width1 || height != height1)
+        if (keepOriginalSize && (width != width1 || height != height1))
         {
             SetSize(-1, -1, width, height);
         }
     }
-    */
 }
 
 void wxWindow::SetFont(const wxFont& font)
@@ -3103,4 +3100,83 @@ void wxWindow::SetFont(const wxFont& font)
     ChangeFont();
 }
 
+void wxWindow::ClearUpdateRects()
+{
+    wxNode* node = m_updateRects.First();
+    while (node)
+    {
+        wxRect* rect = (wxRect*) node->Data();
+        delete rect;
+        node = node->Next();
+    }
+    m_updateRects.Clear();
+}
+
+bool wxWindow::ProcessAccelerator(wxKeyEvent& event)
+{
+    if (!m_acceleratorTable.Ok())
+        return FALSE;
+
+    int count = m_acceleratorTable.GetCount();
+    wxAcceleratorEntry* entries = m_acceleratorTable.GetEntries();
+    int i;
+    for (i = 0; i < count; i++)
+    {
+        wxAcceleratorEntry* entry = & (entries[i]);
+        if (entry->MatchesEvent(event))
+        {
+            // Bingo, we have a match. Now find a control
+            // that matches the entry command id.
+
+            // Need to go up to the top of the window hierarchy,
+            // since it might be e.g. a menu item
+            wxWindow* parent = this;
+            while (parent && !parent->IsKindOf(CLASSINFO(wxFrame)) && !parent->IsKindOf(CLASSINFO(wxDialog)))
+                parent = parent->GetParent();
+
+            if (!parent)
+                return FALSE;
+
+            if (parent->IsKindOf(CLASSINFO(wxFrame)))
+            {
+                // Try for a menu command
+                wxFrame* frame = (wxFrame*) parent;
+                if (frame->GetMenuBar())
+                {
+                    wxMenuItem* item = frame->GetMenuBar()->FindItemForId(entry->GetCommand());
+                    if (item)
+                    {
+                        wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, entry->GetCommand());
+                        commandEvent.SetEventObject(frame);
+
+                        // If ProcessEvent returns TRUE (it was handled), then
+                        // the calling code will skip the event handling.
+                        return frame->GetEventHandler()->ProcessEvent(commandEvent);
+                    }
+                }
+            }
+
+            // Find a child matching the command id
+            wxWindow* child = parent->FindWindow(entry->GetCommand());
+
+            // No such child
+            if (!child)
+                return FALSE;
+
+            // Now we process those kinds of windows that we can.
+            // For now, only buttons.
+            if (child->IsKindOf(CLASSINFO(wxButton)))
+            {
+                wxCommandEvent commandEvent (wxEVT_COMMAND_BUTTON_CLICKED, child->GetId());
+                commandEvent.SetEventObject(child);
+                return child->GetEventHandler()->ProcessEvent(commandEvent);
+            }
+
+            return FALSE;
+        } // matches event
+    }// for
+
+    // We didn't match the key event against an accelerator.
+    return FALSE;
+}