From 02e8b2f9fbdfcd25080c42082d637da257c20094 Mon Sep 17 00:00:00 2001 From: Julian Smart Date: Sun, 20 Sep 1998 07:35:20 +0000 Subject: [PATCH] More Motif stuff, minor stubs correction git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@758 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/motif/button.h | 3 - include/wx/motif/checkbox.h | 2 - include/wx/motif/private.h | 14 ++ include/wx/motif/stattext.h | 4 - include/wx/motif/textctrl.h | 12 +- include/wx/motif/window.h | 21 +- include/wx/msw/window.h | 2 +- include/wx/stubs/window.h | 3 + src/motif/button.cpp | 94 ++++++-- src/motif/checkbox.cpp | 62 ++++-- src/motif/control.cpp | 38 +++- src/motif/stattext.cpp | 38 +++- src/motif/textctrl.cpp | 201 +++++++++++++++++- src/motif/wave.cpp | 4 +- src/motif/window.cpp | 412 ++++++++++++++++++++++++++++++++++-- src/stubs/wave.cpp | 4 +- src/stubs/window.cpp | 11 + 17 files changed, 835 insertions(+), 90 deletions(-) diff --git a/include/wx/motif/button.h b/include/wx/motif/button.h index 427b96d63b..ee31d5c7f1 100644 --- a/include/wx/motif/button.h +++ b/include/wx/motif/button.h @@ -42,10 +42,7 @@ class WXDLLEXPORT wxButton: public wxControl const wxValidator& validator = wxDefaultValidator, const wxString& name = wxButtonNameStr); - virtual void SetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO); virtual void SetDefault(); - virtual void SetLabel(const wxString& label); - virtual wxString GetLabel() const ; virtual void Command(wxCommandEvent& event); }; diff --git a/include/wx/motif/checkbox.h b/include/wx/motif/checkbox.h index a115d5befc..71d0ea4a3f 100644 --- a/include/wx/motif/checkbox.h +++ b/include/wx/motif/checkbox.h @@ -44,8 +44,6 @@ class WXDLLEXPORT wxCheckBox: public wxControl const wxString& name = wxCheckBoxNameStr); virtual void SetValue(bool); virtual bool GetValue() const ; - virtual void SetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO); - virtual void SetLabel(const wxString& label); virtual void Command(wxCommandEvent& event); }; diff --git a/include/wx/motif/private.h b/include/wx/motif/private.h index 3a6732a7cb..6d5ef73e91 100644 --- a/include/wx/motif/private.h +++ b/include/wx/motif/private.h @@ -28,6 +28,20 @@ extern char * wxFindAccelerator (char *s); extern XmString wxFindAcceleratorText (char *s); extern int wxCharCodeXToWX(KeySym keySym); extern KeySym wxCharCodeWXToX(int id); +bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, Widget widget, XEvent *xevent); +bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win, Widget widget, XEvent *xevent); + +#define wxNO_COLORS 0x00 +#define wxBACK_COLORS 0x01 +#define wxFORE_COLORS 0x02 + +extern XColor itemColors[5] ; + +#define wxBACK_INDEX 0 +#define wxFORE_INDEX 1 +#define wxSELE_INDEX 2 +#define wxTOPS_INDEX 3 +#define wxBOTS_INDEX 4 #endif // _WX_PRIVATE_H_ diff --git a/include/wx/motif/stattext.h b/include/wx/motif/stattext.h index 9dfa9d23e0..a1268cf7e1 100644 --- a/include/wx/motif/stattext.h +++ b/include/wx/motif/stattext.h @@ -43,10 +43,6 @@ class WXDLLEXPORT wxStaticText: public wxControl long style = 0, const wxString& name = wxStaticTextNameStr); - // accessors - void SetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO); - void SetLabel(const wxString&); - // operations virtual void Command(wxCommandEvent& WXUNUSED(event)) {}; virtual void ProcessCommand(wxCommandEvent& WXUNUSED(event)) {}; diff --git a/include/wx/motif/textctrl.h b/include/wx/motif/textctrl.h index 6cc2b83033..fe4c05955e 100644 --- a/include/wx/motif/textctrl.h +++ b/include/wx/motif/textctrl.h @@ -78,7 +78,6 @@ public: // operations // ---------- - virtual void SetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO); // Clipboard operations virtual void Copy(); @@ -122,16 +121,23 @@ public: // callbacks // --------- void OnDropFiles(wxDropFilesEvent& event); -// void OnChar(wxKeyEvent& event); // Process 'enter' if required + void OnChar(wxKeyEvent& event); // void OnEraseBackground(wxEraseEvent& event); // Implementation // -------------- virtual void Command(wxCommandEvent& event); + //// Motif-specific + inline void SetModified(bool mod) { m_modified = mod; } + virtual WXWidget GetTopWidget() const; + protected: wxString m_fileName; - +public: + // Motif-specific + void* m_tempCallbackStruct; + bool m_modified; DECLARE_EVENT_TABLE() }; diff --git a/include/wx/motif/window.h b/include/wx/motif/window.h index cbe336c021..f85c06aef7 100644 --- a/include/wx/motif/window.h +++ b/include/wx/motif/window.h @@ -283,6 +283,9 @@ public: inline void SetWindowStyleFlag(long flag); inline long GetWindowStyleFlag() const; + // Handle a control command + virtual void OnCommand(wxWindow& win, wxCommandEvent& event); + // Set/get event handler inline void SetEventHandler(wxEvtHandler *handler); inline wxEvtHandler *GetEventHandler() const; @@ -460,17 +463,32 @@ public: // message, e.g. arrange status bar, toolbar etc. virtual bool PreResize() { return TRUE; } - // Get main widget for this window + // Get main widget for this window, e.g. a text widget virtual WXWidget GetMainWidget() const; // Get the client widget for this window (something we can // create other windows on) virtual WXWidget GetClientWidget() const; + // Get the top widget for this window, e.g. the scrolled widget parent + // of a multi-line text widget. Top means, top in the window hierarchy + // that implements this window. + virtual WXWidget GetTopWidget() const; virtual void SetMainWidget(WXWidget w) { m_mainWidget = w; } + bool CanAddEventHandler() const { return m_canAddEventHandler; } + void SetCanAddEventHandler(bool flag) { m_canAddEventHandler = flag; } // Get the underlying X window and display virtual WXWindow GetXWindow() const; virtual WXDisplay *GetXDisplay() const; + // Change properties + virtual void ChangeColour(WXWidget widget); + virtual void ChangeFont(WXWidget widget); + + // Adds the widget to the hash table and adds event handlers. + bool AttachWidget (wxWindow* parent, WXWidget mainWidget, + WXWidget formWidget, int x, int y, int width, int height); + bool DetachWidget(WXWidget widget); + // Generates a paint event virtual void DoPaint(); @@ -520,6 +538,7 @@ public: public: /// Motif-specific + bool m_canAddEventHandler; bool m_button1Pressed; bool m_button2Pressed; bool m_button3Pressed; diff --git a/include/wx/msw/window.h b/include/wx/msw/window.h index b1be14ed17..ed9fc7abde 100644 --- a/include/wx/msw/window.h +++ b/include/wx/msw/window.h @@ -295,7 +295,7 @@ public: inline bool GetDoubleClick(void) const; inline void AllowDoubleClick(bool value) { SetDoubleClick(value); } - // Old way to handle a control command + // Handle a control command virtual void OnCommand(wxWindow& win, wxCommandEvent& event); // Set/get event handler diff --git a/include/wx/stubs/window.h b/include/wx/stubs/window.h index 6b33ddf12a..cec262e872 100644 --- a/include/wx/stubs/window.h +++ b/include/wx/stubs/window.h @@ -283,6 +283,9 @@ public: inline void SetWindowStyleFlag(long flag); inline long GetWindowStyleFlag() const; + // Handle a control command + virtual void OnCommand(wxWindow& win, wxCommandEvent& event); + // Set/get event handler inline void SetEventHandler(wxEvtHandler *handler); inline wxEvtHandler *GetEventHandler() const; diff --git a/src/motif/button.cpp b/src/motif/button.cpp index d7cdab1c6a..455f2e17fb 100644 --- a/src/motif/button.cpp +++ b/src/motif/button.cpp @@ -15,6 +15,13 @@ #include "wx/button.h" +#include +#include + +#include "wx/motif/private.h" + +void wxButtonCallback (Widget w, XtPointer clientData, XtPointer ptr); + #if !USE_SHARED_LIBRARY IMPLEMENT_DYNAMIC_CLASS(wxButton, wxControl) #endif @@ -38,14 +45,40 @@ bool wxButton::Create(wxWindow *parent, wxWindowID id, const wxString& label, else m_windowId = id; - // TODO: create button + char* label1 = (label.IsNull() ? "" : (char*) (const char*) label); - return FALSE; -} + XmString text = XmStringCreateSimple (label1); + Widget parentWidget = (Widget) parent->GetClientWidget(); -void wxButton::SetSize(int x, int y, int width, int height, int sizeFlags) -{ - // TODO + /* + * Patch Note (important) + * There is no major reason to put a defaultButtonThickness here. + * Not requesting it give the ability to put wxButton with a spacing + * as small as requested. However, if some button become a DefaultButton, + * other buttons are no more aligned -- This is why we set + * defaultButtonThickness of ALL buttons belonging to the same wxPanel, + * in the ::SetDefaultButton method. + */ + m_mainWidget = (WXWidget) XtVaCreateManagedWidget ("button", + xmPushButtonWidgetClass, + parentWidget, + XmNlabelString, text, +// XmNdefaultButtonShadowThickness, 1, // See comment for wxButton::SetDefault + NULL); + + XmStringFree (text); + + XtAddCallback ((Widget) m_mainWidget, XmNactivateCallback, (XtCallbackProc) wxButtonCallback, + (XtPointer) this); + + + SetCanAddEventHandler(TRUE); + AttachWidget (parent, m_mainWidget, (WXWidget) NULL, pos.x, pos.y, size.x, size.y); + + SetFont(* parent->GetFont()); + ChangeColour(m_mainWidget); + + return TRUE; } void wxButton::SetDefault() @@ -54,18 +87,32 @@ void wxButton::SetDefault() if (parent) parent->SetDefaultItem(this); - // TODO: make button the default -} - -wxString wxButton::GetLabel() const -{ - // TODO - return wxString(""); -} - -void wxButton::SetLabel(const wxString& label) -{ - // TODO + // We initially do not set XmNdefaultShadowThickness, to have small buttons. + // Unfortunately, buttons are now mis-aligned. We try to correct this + // now -- setting this ressource to 1 for each button in the same row. + // Because it's very hard to find wxButton in the same row, + // correction is straighforward: we set resource for all wxButton + // in this parent (but not sub panels) + for (wxNode * node = parent->GetChildren ()->First (); node; node = node->Next ()) + { + wxButton *item = (wxButton *) node->Data (); + if (item->IsKindOf(CLASSINFO(wxButton))) + { + bool managed = XtIsManaged((Widget) item->GetMainWidget()); + if (managed) + XtUnmanageChild ((Widget) item->GetMainWidget()); + + XtVaSetValues ((Widget) item->GetMainWidget(), + XmNdefaultButtonShadowThickness, 1, + NULL); + + if (managed) + XtManageChild ((Widget) item->GetMainWidget()); + } + } // while + +// XtVaSetValues((Widget)handle, XmNshowAsDefault, 1, NULL); + XtVaSetValues ((Widget) parent->GetMainWidget(), XmNdefaultButton, (Widget) GetMainWidget(), NULL); } void wxButton::Command (wxCommandEvent & event) @@ -73,3 +120,14 @@ void wxButton::Command (wxCommandEvent & event) ProcessCommand (event); } +void wxButtonCallback (Widget w, XtPointer clientData, XtPointer ptr) +{ + if (!wxGetWindowFromTable(w)) + // Widget has been deleted! + return; + + wxButton *item = (wxButton *) clientData; + wxCommandEvent event (wxEVT_COMMAND_BUTTON_CLICKED, item->GetId()); + event.SetEventObject(item); + item->ProcessCommand (event); +} diff --git a/src/motif/checkbox.cpp b/src/motif/checkbox.cpp index 8755f5d5a4..4f2330ab32 100644 --- a/src/motif/checkbox.cpp +++ b/src/motif/checkbox.cpp @@ -15,6 +15,16 @@ #include "wx/checkbox.h" +#include +#include +#include +#include + +#include "wx/motif/private.h" + +void wxCheckBoxCallback (Widget w, XtPointer clientData, + XtPointer ptr); + #if !USE_SHARED_LIBRARY IMPLEMENT_DYNAMIC_CLASS(wxCheckBox, wxControl) IMPLEMENT_DYNAMIC_CLASS(wxBitmapCheckBox, wxCheckBox) @@ -38,30 +48,42 @@ bool wxCheckBox::Create(wxWindow *parent, wxWindowID id, const wxString& label, else m_windowId = id; - // TODO: create checkbox + char* label1 = (label.IsNull() ? "" : (char*) (const char*) label); - return FALSE; -} + XmString text = XmStringCreateSimple (label1); + Widget parentWidget = (Widget) parent->GetClientWidget(); -void wxCheckBox::SetLabel(const wxString& label) -{ - // TODO -} + m_mainWidget = (WXWidget) XtVaCreateManagedWidget ("toggle", + xmToggleButtonWidgetClass, parentWidget, + XmNlabelString, text, + NULL); + XmStringFree (text); -void wxCheckBox::SetSize(int x, int y, int width, int height, int sizeFlags) -{ - // TODO + XtAddCallback ((Widget) m_mainWidget, XmNvalueChangedCallback, (XtCallbackProc) wxCheckBoxCallback, + (XtPointer) this); + + XmToggleButtonSetState ((Widget) m_mainWidget, FALSE, TRUE); + + SetCanAddEventHandler(TRUE); + AttachWidget (parent, m_mainWidget, (WXWidget) NULL, pos.x, pos.y, size.x, size.y); + + ChangeColour(m_mainWidget); + SetFont(* parent->GetFont()); + + return TRUE; } void wxCheckBox::SetValue(bool val) { - // TODO + // TODO: m_inSetValue + // inSetValue = TRUE; + XmToggleButtonSetState ((Widget) m_mainWidget, (Boolean) val, TRUE); + // inSetValue = FALSE; } bool wxCheckBox::GetValue() const { - // TODO - return FALSE; + return (XmToggleButtonGetState ((Widget) m_mainWidget) != 0); } void wxCheckBox::Command (wxCommandEvent & event) @@ -114,4 +136,16 @@ bool wxBitmapCheckBox::GetValue() const return FALSE; } - +void wxCheckBoxCallback (Widget w, XtPointer clientData, + XtPointer ptr) +{ + wxCheckBox *item = (wxCheckBox *) clientData; + // TODO + // if (item->inSetValue) + // return; + + wxCommandEvent event (wxEVT_COMMAND_CHECKBOX_CLICKED, item->GetId()); + event.SetInt((int) item->GetValue ()); + event.SetEventObject(item); + item->ProcessCommand (event); +} diff --git a/src/motif/control.cpp b/src/motif/control.cpp index aa0baba9eb..4e708a5c14 100644 --- a/src/motif/control.cpp +++ b/src/motif/control.cpp @@ -14,6 +14,9 @@ #endif #include "wx/control.h" +#include "wx/utils.h" + +#include #if !USE_SHARED_LIBRARY IMPLEMENT_ABSTRACT_CLASS(wxControl, wxWindow) @@ -44,13 +47,42 @@ wxControl::~wxControl() void wxControl::SetLabel(const wxString& label) { - // TODO + if (!GetMainWidget()) + return; + + wxStripMenuCodes((char*) (const char*) label, wxBuffer); + + XmString text = XmStringCreateSimple (wxBuffer); + XtVaSetValues ((Widget) GetMainWidget(), + XmNlabelString, text, + XmNlabelType, XmSTRING, + NULL); + XmStringFree (text); } wxString wxControl::GetLabel() const { - // TODO - return wxString(""); + if (!GetMainWidget()) + return wxEmptyString; + + XmString text; + char *s; + XtVaGetValues ((Widget) GetMainWidget(), + XmNlabelString, &text, + NULL); + + if (XmStringGetLtoR (text, XmSTRING_DEFAULT_CHARSET, &s)) + { + wxString str(s); + XtFree (s); + XmStringFree(text); + return str; + } + else + { + XmStringFree(text); + return wxEmptyString; + } } void wxControl::ProcessCommand (wxCommandEvent & event) diff --git a/src/motif/stattext.cpp b/src/motif/stattext.cpp index 294f51036c..cc0aa547f0 100644 --- a/src/motif/stattext.cpp +++ b/src/motif/stattext.cpp @@ -18,6 +18,10 @@ #include +#include +#include +#include + #if !USE_SHARED_LIBRARY IMPLEMENT_DYNAMIC_CLASS(wxStaticText, wxControl) #endif @@ -42,19 +46,33 @@ bool wxStaticText::Create(wxWindow *parent, wxWindowID id, m_windowStyle = style; + char* label1 = (label.IsNull() ? "" : (char*) (const char*) label); + + Widget parentWidget = (Widget) parent->GetClientWidget(); + + XmString text = XmStringCreateSimple (label1); + + m_mainWidget = (WXWidget) XtVaCreateManagedWidget ((char*) (const char*) name, + xmLabelWidgetClass, + parentWidget, + XmNlabelString, text, + XmNalignment, + ((style & wxALIGN_RIGHT) ? XmALIGNMENT_END : + ((style & wxALIGN_CENTRE) ? XmALIGNMENT_CENTER : + XmALIGNMENT_BEGINNING)), + NULL); + + XmStringFree (text); + + SetCanAddEventHandler(TRUE); + AttachWidget (parent, m_mainWidget, (WXWidget) NULL, pos.x, pos.y, size.x, size.y); + SetFont(* parent->GetFont()); - // TODO - return FALSE; -} + ChangeColour (m_mainWidget); + // ChangeFont (m_mainWidget); -void wxStaticText::SetSize(int x, int y, int width, int height, int sizeFlags) -{ - // TODO + return TRUE; } -void wxStaticText::SetLabel(const wxString& label) -{ - // TODO -} diff --git a/src/motif/textctrl.cpp b/src/motif/textctrl.cpp index 6727160c89..e03e6b04f7 100644 --- a/src/motif/textctrl.cpp +++ b/src/motif/textctrl.cpp @@ -30,11 +30,28 @@ #endif #endif +#include +#include +#include +#include + +#include "wx/motif/private.h" + +static void +wxTextWindowChangedProc (Widget w, XtPointer clientData, XtPointer ptr); +static void +wxTextWindowModifyProc (Widget w, XtPointer clientData, XmTextVerifyCallbackStruct *cbs); +static void +wxTextWindowGainFocusProc (Widget w, XtPointer clientData, XmAnyCallbackStruct *cbs); +static void +wxTextWindowLoseFocusProc (Widget w, XtPointer clientData, XmAnyCallbackStruct *cbs); + #if !USE_SHARED_LIBRARY IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl) BEGIN_EVENT_TABLE(wxTextCtrl, wxControl) EVT_DROP_FILES(wxTextCtrl::OnDropFiles) + EVT_CHAR(wxTextCtrl::OnChar) END_EVENT_TABLE() #endif @@ -45,6 +62,8 @@ wxTextCtrl::wxTextCtrl() #endif { m_fileName = ""; + m_tempCallbackStruct = (void*) NULL; + m_modified = FALSE; } bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, @@ -54,7 +73,10 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, const wxValidator& validator, const wxString& name) { + m_tempCallbackStruct = (void*) NULL; + m_modified = FALSE; m_fileName = ""; + SetName(name); SetValidator(validator); if (parent) parent->AddChild(this); @@ -66,21 +88,76 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, else m_windowId = id; + Widget parentWidget = (Widget) parent->GetClientWidget(); + + bool wantHorizScrolling = ((m_windowStyle & wxHSCROLL) != 0); + + // If we don't have horizontal scrollbars, we want word wrap. + bool wantWordWrap = !wantHorizScrolling; + + if (m_windowStyle & wxTE_MULTILINE) + { + Arg args[2]; + XtSetArg (args[0], XmNscrollHorizontal, wantHorizScrolling ? True : False); + XtSetArg (args[1], XmNwordWrap, wantWordWrap ? True : False); + + m_mainWidget = (WXWidget) XmCreateScrolledText (parentWidget, (char*) (const char*) name, args, 2); + + XtVaSetValues ((Widget) m_mainWidget, + XmNeditable, ((style & wxTE_READONLY) ? False : True), + XmNeditMode, XmMULTI_LINE_EDIT, + NULL); + XtManageChild ((Widget) m_mainWidget); + } + else + { + m_mainWidget = (WXWidget) XtVaCreateManagedWidget ((char*) (const char*) name, + xmTextWidgetClass, parentWidget, + NULL); + + // TODO: Is this relevant? What does it do? + int noCols = 2; + if (!value.IsNull() && (value.Length() > (unsigned int) noCols)) + noCols = value.Length(); + XtVaSetValues ((Widget) m_mainWidget, + XmNcolumns, noCols, + NULL); + } + + if (!value.IsNull()) + XmTextSetString ((Widget) m_mainWidget, (char*) (const char*) value); + + XtAddCallback((Widget) m_mainWidget, XmNvalueChangedCallback, (XtCallbackProc)wxTextWindowChangedProc, (XtPointer)this); + + XtAddCallback((Widget) m_mainWidget, XmNmodifyVerifyCallback, (XtCallbackProc)wxTextWindowModifyProc, (XtPointer)this); + +// XtAddCallback((Widget) m_mainWidget, XmNactivateCallback, (XtCallbackProc)wxTextWindowModifyProc, (XtPointer)this); + + XtAddCallback((Widget) m_mainWidget, XmNfocusCallback, (XtCallbackProc)wxTextWindowGainFocusProc, (XtPointer)this); + + XtAddCallback((Widget) m_mainWidget, XmNlosingFocusCallback, (XtCallbackProc)wxTextWindowLoseFocusProc, (XtPointer)this); + + SetCanAddEventHandler(TRUE); + AttachWidget (parent, m_mainWidget, (WXWidget) NULL, pos.x, pos.y, size.x, size.y); + + SetFont(* parent->GetFont()); + ChangeColour(m_mainWidget); + return TRUE; } -wxString wxTextCtrl::GetValue() const +WXWidget wxTextCtrl::GetTopWidget() const { - // TODO - return wxString(""); + return ((m_windowStyle & wxTE_MULTILINE) ? (WXWidget) XtParent((Widget) m_mainWidget) : m_mainWidget); } -void wxTextCtrl::SetValue(const wxString& value) +wxString wxTextCtrl::GetValue() const { // TODO + return wxString(""); } -void wxTextCtrl::SetSize(int x, int y, int width, int height, int sizeFlags) +void wxTextCtrl::SetValue(const wxString& value) { // TODO } @@ -213,13 +290,15 @@ void wxTextCtrl::WriteText(const wxString& text) void wxTextCtrl::Clear() { - // TODO + XmTextSetString ((Widget) m_mainWidget, ""); + // TODO: do we need position flag? + // m_textPosition = 0; + m_modified = FALSE; } bool wxTextCtrl::IsModified() const { - // TODO - return FALSE; + return m_modified; } // Makes 'unmodified' @@ -436,3 +515,109 @@ wxTextCtrl& wxTextCtrl::operator<<(const char c) return *this; } +void wxTextCtrl::OnChar(wxKeyEvent& event) +{ + if (m_tempCallbackStruct) + { + XmTextVerifyCallbackStruct *textStruct = + (XmTextVerifyCallbackStruct *) m_tempCallbackStruct; + textStruct->doit = True; + if (isascii(event.m_keyCode) && (textStruct->text->length == 1)) + { + textStruct->text->ptr[0] = ((event.m_keyCode == WXK_RETURN) ? 10 : event.m_keyCode); + } + } +} + +static void +wxTextWindowChangedProc (Widget w, XtPointer clientData, XtPointer ptr) +{ + if (!wxGetWindowFromTable(w)) + // Widget has been deleted! + return; + + wxTextCtrl *tw = (wxTextCtrl *) clientData; + tw->SetModified(TRUE); +} + +static void +wxTextWindowModifyProc (Widget w, XtPointer clientData, XmTextVerifyCallbackStruct *cbs) +{ + wxTextCtrl *tw = (wxTextCtrl *) clientData; + + // If we're already within an OnChar, return: probably + // a programmatic insertion. + if (tw->m_tempCallbackStruct) + return; + + // Check for a backspace + if (cbs->startPos == (cbs->currInsert - 1)) + { + tw->m_tempCallbackStruct = (void*) cbs; + + wxKeyEvent event (wxEVT_CHAR); + event.SetId(tw->GetId()); + event.m_keyCode = WXK_DELETE; + event.SetEventObject(tw); + + // Only if wxTextCtrl::OnChar is called + // will this be set to True (and the character + // passed through) + cbs->doit = False; + + tw->GetEventHandler()->ProcessEvent(event); + + tw->m_tempCallbackStruct = NULL; + + return; + } + + // Pasting operation: let it through without + // calling OnChar + if (cbs->text->length > 1) + return; + + // Something other than text + if (cbs->text->ptr == NULL) + return; + + tw->m_tempCallbackStruct = (void*) cbs; + + wxKeyEvent event (wxEVT_CHAR); + event.SetId(tw->GetId()); + event.SetEventObject(tw); + event.m_keyCode = (cbs->text->ptr[0] == 10 ? 13 : cbs->text->ptr[0]); + + // Only if wxTextCtrl::OnChar is called + // will this be set to True (and the character + // passed through) + cbs->doit = False; + + tw->GetEventHandler()->ProcessEvent(event); + + tw->m_tempCallbackStruct = NULL; +} + +static void +wxTextWindowGainFocusProc (Widget w, XtPointer clientData, XmAnyCallbackStruct *cbs) +{ + if (!wxGetWindowFromTable(w)) + return; + + wxTextCtrl *tw = (wxTextCtrl *) clientData; + wxFocusEvent event(wxEVT_SET_FOCUS, tw->GetId()); + event.SetEventObject(tw); + tw->GetEventHandler()->ProcessEvent(event); +} + +static void +wxTextWindowLoseFocusProc (Widget w, XtPointer clientData, XmAnyCallbackStruct *cbs) +{ + if (!wxGetWindowFromTable(w)) + return; + + wxTextCtrl *tw = (wxTextCtrl *) clientData; + wxFocusEvent event(wxEVT_KILL_FOCUS, tw->GetId()); + event.SetEventObject(tw); + tw->GetEventHandler()->ProcessEvent(event); +} diff --git a/src/motif/wave.cpp b/src/motif/wave.cpp index c51c675f62..177586f130 100644 --- a/src/motif/wave.cpp +++ b/src/motif/wave.cpp @@ -18,12 +18,12 @@ #include "wx/stubs/wave.h" wxWave::wxWave() - : m_waveLength(0), m_isResource(FALSE), m_waveData(NULL) + : m_waveData(NULL), m_waveLength(0), m_isResource(FALSE) { } wxWave::wxWave(const wxString& sFileName, bool isResource) - : m_waveLength(0), m_isResource(isResource), m_waveData(NULL) + : m_waveData(NULL), m_waveLength(0), m_isResource(FALSE) { Create(sFileName, isResource); } diff --git a/src/motif/window.cpp b/src/motif/window.cpp index 3f2ba314ed..5e8e991bef 100644 --- a/src/motif/window.cpp +++ b/src/motif/window.cpp @@ -52,6 +52,10 @@ 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 wxPanelItemEventHandler (Widget wid, + XtPointer client_data, + XEvent* event, + Boolean *continueToDispatch); #define event_left_is_down(x) ((x)->xbutton.state & Button1Mask) #define event_middle_is_down(x) ((x)->xbutton.state & Button2Mask) @@ -127,6 +131,7 @@ wxWindow::wxWindow() m_pixmapOffsetY = 0; m_lastTS = 0; m_lastButton = 0; + m_canAddEventHandler = FALSE; } // Destructor @@ -134,6 +139,9 @@ wxWindow::~wxWindow() { //// Motif-specific + if (GetMainWidget()) + DetachWidget(GetMainWidget()); // Removes event handlers + // If m_drawingArea, we're a fully-fledged window with drawing area, scrollbars etc. (what wxCanvas used to be) if (m_drawingArea) { @@ -179,7 +187,6 @@ wxWindow::~wxWindow() } } - //// Generic stuff // Have to delete constraints/sizer FIRST otherwise @@ -271,6 +278,7 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id, m_windowParent = NULL; // Motif-specific + m_canAddEventHandler = FALSE; m_mainWidget = (WXWidget) 0; m_button1Pressed = FALSE; m_button2Pressed = FALSE; @@ -504,7 +512,7 @@ void wxWindow::GetSize(int *x, int *y) const return; } - Widget widget = (Widget) GetMainWidget(); + Widget widget = (Widget) GetTopWidget(); Dimension xx, yy; XtVaGetValues(widget, XmNwidth, &xx, XmNheight, &yy, NULL); *x = xx; *y = yy; @@ -517,7 +525,7 @@ void wxWindow::GetPosition(int *x, int *y) const CanvasGetPosition(x, y); return; } - Widget widget = (Widget) GetMainWidget(); + Widget widget = (Widget) GetTopWidget(); Position xx, yy; XtVaGetValues(widget, XmNx, &xx, XmNy, &yy, NULL); *x = xx; *y = yy; @@ -530,7 +538,7 @@ void wxWindow::ScreenToClient(int *x, int *y) const void wxWindow::ClientToScreen(int *x, int *y) const { - Widget widget = (Widget) GetMainWidget(); + Widget widget = (Widget) GetClientWidget(); Display *display = XtDisplay(widget); Window rootWindow = RootWindowOfScreen(XtScreen(widget)); Window thisWindow; @@ -569,7 +577,7 @@ void wxWindow::SetCursor(const wxCursor& cursor) // Get size *available for subwindows* i.e. excluding menu bar etc. void wxWindow::GetClientSize(int *x, int *y) const { - Widget widget = (Widget) GetMainWidget(); + Widget widget = (Widget) GetTopWidget(); Dimension xx, yy; XtVaGetValues(widget, XmNwidth, &xx, XmNheight, &yy, NULL); *x = xx; *y = yy; @@ -582,7 +590,13 @@ void wxWindow::SetSize(int x, int y, int width, int height, int sizeFlags) CanvasSetSize(x, y, width, height, sizeFlags); return; } - Widget widget = (Widget) GetMainWidget(); + Widget widget = (Widget) GetTopWidget(); + if (!widget) + return; + + bool managed = XtIsManaged( widget ); + if (managed) + XtUnmanageChild(widget); if (x > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE)) XtVaSetValues(widget, XmNx, x, NULL); @@ -593,6 +607,9 @@ void wxWindow::SetSize(int x, int y, int width, int height, int sizeFlags) if (height > -1) XtVaSetValues(widget, XmNheight, height, NULL); + if (managed) + XtManageChild(widget); + wxSizeEvent sizeEvent(wxSize(width, height), GetId()); sizeEvent.SetEventObject(this); @@ -607,7 +624,7 @@ void wxWindow::SetClientSize(int width, int height) return; } - Widget widget = (Widget) GetMainWidget(); + Widget widget = (Widget) GetTopWidget(); if (width > -1) XtVaSetValues(widget, XmNwidth, width, NULL); @@ -648,7 +665,7 @@ bool wxWindow::Show(bool show) } else { - XtMapWidget((Widget) GetMainWidget()); + XtMapWidget((Widget) GetTopWidget()); } } else @@ -659,7 +676,7 @@ bool wxWindow::Show(bool show) } else { - XtUnmapWidget((Widget) GetMainWidget()); + XtUnmapWidget((Widget) GetTopWidget()); } } @@ -1072,6 +1089,17 @@ void wxWindow::MakeModal(bool modal) } } +// If nothing defined for this, try the parent. +// E.g. we may be a button loaded from a resource, with no callback function +// defined. +void wxWindow::OnCommand(wxWindow& win, wxCommandEvent& event) +{ + if (GetEventHandler()->ProcessEvent(event) ) + return; + if (m_windowParent) + m_windowParent->GetEventHandler()->OnCommand(win, event); +} + void wxWindow::SetConstraints(wxLayoutConstraints *c) { if (m_constraints) @@ -1619,15 +1647,15 @@ void wxWindow::OnIdle(wxIdleEvent& event) // Raise the window to the top of the Z order void wxWindow::Raise() { - Window window = XtWindow((Widget) GetMainWidget()); - XRaiseWindow(XtDisplay((Widget) GetMainWidget()), window); + Window window = XtWindow((Widget) GetTopWidget()); + XRaiseWindow(XtDisplay((Widget) GetTopWidget()), window); } // Lower the window to the bottom of the Z order void wxWindow::Lower() { - Window window = XtWindow((Widget) GetMainWidget()); - XLowerWindow(XtDisplay((Widget) GetMainWidget()), window); + Window window = XtWindow((Widget) GetTopWidget()); + XLowerWindow(XtDisplay((Widget) GetTopWidget()), window); } bool wxWindow::AcceptsFocus() const @@ -1718,11 +1746,6 @@ wxWindow *wxGetWindowFromTable(Widget w) void wxDeleteWindowFromTable(Widget w) { -#if DEBUG -// printf("Deleting widget %ld\n", w); -#endif -// wxWindow *win = (wxWindow *)wxWidgetHashTable->Get ((long) w); - wxWidgetHashTable->Delete((long)w); } @@ -1750,7 +1773,12 @@ WXWidget wxWindow::GetClientWidget() const if (m_drawingArea != (WXWidget) 0) return m_drawingArea; else - return m_mainWidget; + return GetMainWidget(); +} + +WXWidget wxWindow::GetTopWidget() const +{ + return GetMainWidget(); } void wxCanvasRepaintProc (Widget drawingArea, XtPointer clientData, @@ -2290,3 +2318,349 @@ void wxWindow::CanvasGetPosition (int *x, int *y) const *x = xx; *y = yy; } + +// Add to hash table, add event handler +bool wxWindow::AttachWidget (wxWindow* parent, WXWidget mainWidget, + WXWidget formWidget, int x, int y, int width, int height) +{ + wxAddWindowToTable((Widget) mainWidget, this); + if (CanAddEventHandler()) + { + XtAddEventHandler((Widget) mainWidget, + ButtonPressMask | ButtonReleaseMask | PointerMotionMask, // | KeyPressMask, + False, + wxPanelItemEventHandler, + (XtPointer) this); + } + + if (!formWidget) + { + XtTranslations ptr; + XtOverrideTranslations ((Widget) mainWidget, + ptr = XtParseTranslationTable (": resize()")); + XtFree ((char *) ptr); + } + + // Some widgets have a parent form widget, e.g. wxRadioBox + if (formWidget) + { + if (!wxAddWindowToTable((Widget) formWidget, this)) + return FALSE; + + XtTranslations ptr; + XtOverrideTranslations ((Widget) formWidget, + ptr = XtParseTranslationTable (": resize()")); + XtFree ((char *) ptr); + } + + if (x == -1) + x = 0; + if (y == -1) + y = 0; + SetSize (x, y, width, height); + + return TRUE; +} + +// Remove event handler, remove from hash table +bool wxWindow::DetachWidget(WXWidget widget) +{ + if (CanAddEventHandler()) + { + XtRemoveEventHandler((Widget) widget, + ButtonPressMask | ButtonReleaseMask | PointerMotionMask, // | KeyPressMask, + False, + wxPanelItemEventHandler, + (XtPointer)this); + } + + wxDeleteWindowFromTable((Widget) widget); + return TRUE; +} + +void wxPanelItemEventHandler (Widget wid, + XtPointer client_data, + XEvent* event, + Boolean *continueToDispatch) +{ + // Widget can be a label or the actual widget. + + wxWindow *window = (wxWindow *)wxWidgetHashTable->Get((long)wid); + if (window) + { + wxMouseEvent wxevent(0); + if (wxTranslateMouseEvent(wxevent, window, wid, event)) + { + window->GetEventHandler()->ProcessEvent(wxevent); + } + } + // TODO: probably the key to allowing default behaviour + // to happen. + // Say we set a m_doDefault flag to FALSE at the start of this + // function. Then in e.g. wxWindow::OnMouseEvent we can + // call Default() which sets this flag to TRUE, indicating + // that default processing can happen. Thus, behaviour can appear + // to be overridden just by adding an event handler and not calling + // wxWindow::OnWhatever. + // ALSO, maybe we can use this instead of the current way of handling + // drawing area events, to simplify things. + *continueToDispatch = True; +} + +bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, Widget widget, XEvent *xevent) +{ + switch (xevent->xany.type) + { + case EnterNotify: + case LeaveNotify: + case ButtonPress: + case ButtonRelease: + case MotionNotify: + { + wxEventType eventType = wxEVT_NULL; + + if (xevent->xany.type == LeaveNotify) + { + win->m_button1Pressed = FALSE; + win->m_button2Pressed = FALSE; + win->m_button3Pressed = FALSE; + return FALSE; + } + else if (xevent->xany.type == MotionNotify) + { + eventType = wxEVT_MOTION; + } + else if (xevent->xany.type == ButtonPress) + { + if (xevent->xbutton.button == Button1) + { + eventType = wxEVT_LEFT_DOWN; + win->m_button1Pressed = TRUE; + } + else if (xevent->xbutton.button == Button2) + { + eventType = wxEVT_MIDDLE_DOWN; + win->m_button2Pressed = TRUE; + } + else if (xevent->xbutton.button == Button3) + { + eventType = wxEVT_RIGHT_DOWN; + win->m_button3Pressed = TRUE; + } + } + else if (xevent->xany.type == ButtonRelease) + { + if (xevent->xbutton.button == Button1) + { + eventType = wxEVT_LEFT_UP; + win->m_button1Pressed = FALSE; + } + else if (xevent->xbutton.button == Button2) + { + eventType = wxEVT_MIDDLE_UP; + win->m_button2Pressed = FALSE; + } + else if (xevent->xbutton.button == Button3) + { + eventType = wxEVT_RIGHT_UP; + win->m_button3Pressed = FALSE; + } + else return FALSE; + } + else return FALSE; + + wxevent.m_eventHandle = (char *)xevent; + wxevent.SetEventType(eventType); + + Position x1, y1; + XtVaGetValues(widget, XmNx, &x1, XmNy, &y1, NULL); + + int x2, y2; + win->GetPosition(&x2, &y2); + + // The button x/y must be translated to wxWindows + // window space - the widget might be a label or button, + // within a form. + int dx = 0; + int dy = 0; + if (widget != (Widget)win->GetMainWidget()) + { + dx = x1; + dy = y1; + } + + wxevent.m_x = xevent->xbutton.x + dx; + wxevent.m_y = xevent->xbutton.y + dy; + + wxevent.m_leftDown = ((eventType == wxEVT_LEFT_DOWN) + || (event_left_is_down (xevent) + && (eventType != wxEVT_LEFT_UP))); + wxevent.m_middleDown = ((eventType == wxEVT_MIDDLE_DOWN) + || (event_middle_is_down (xevent) + && (eventType != wxEVT_MIDDLE_UP))); + wxevent.m_rightDown = ((eventType == wxEVT_RIGHT_DOWN) + || (event_right_is_down (xevent) + && (eventType != wxEVT_RIGHT_UP))); + + wxevent.m_shiftDown = xevent->xbutton.state & ShiftMask; + wxevent.m_controlDown = xevent->xbutton.state & ControlMask; + return TRUE; + } + } + return FALSE; +} + +bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win, Widget widget, XEvent *xevent) +{ + switch (xevent->xany.type) + { + case KeyPress: + { + char buf[20]; + + KeySym keySym; +// XComposeStatus compose; +// (void) XLookupString ((XKeyEvent *) xevent, buf, 20, &keySym, &compose); + (void) XLookupString ((XKeyEvent *) xevent, buf, 20, &keySym, NULL); + int id = wxCharCodeXToWX (keySym); + + if (xevent->xkey.state & ShiftMask) + wxevent.m_shiftDown = TRUE; + if (xevent->xkey.state & ControlMask) + wxevent.m_controlDown = TRUE; + if (xevent->xkey.state & Mod3Mask) + wxevent.m_altDown = TRUE; + if (xevent->xkey.state & Mod1Mask) + wxevent.m_metaDown = TRUE; + wxevent.SetEventObject(win); + wxevent.m_keyCode = id; + wxevent.SetTimestamp(xevent->xkey.time); + + wxevent.m_x = xevent->xbutton.x; + wxevent.m_y = xevent->xbutton.y; + + if (id > -1) + return TRUE; + else + return FALSE; + break; + } + default: + break; + } + return FALSE; +} + +// TODO From wxWin 1.68. What does it do exactly? +#define YAllocColor XAllocColor + +XColor itemColors[5]; +int wxComputeColors (Display *display, wxColour * back, wxColour * fore) +{ + int result; + static XmColorProc colorProc; + + result = wxNO_COLORS; + + if (back) + { + itemColors[0].red = (((long) back->Red ()) << 8); + itemColors[0].green = (((long) back->Green ()) << 8); + itemColors[0].blue = (((long) back->Blue ()) << 8); + itemColors[0].flags = DoRed | DoGreen | DoBlue; + if (colorProc == (XmColorProc) NULL) + { + // Get a ptr to the actual function + colorProc = XmSetColorCalculation ((XmColorProc) NULL); + // And set it back to motif. + XmSetColorCalculation (colorProc); + } + (*colorProc) (&itemColors[wxBACK_INDEX], + &itemColors[wxFORE_INDEX], + &itemColors[wxSELE_INDEX], + &itemColors[wxTOPS_INDEX], + &itemColors[wxBOTS_INDEX]); + result = wxBACK_COLORS; + } + if (fore) + { + itemColors[wxFORE_INDEX].red = (((long) fore->Red ()) << 8); + itemColors[wxFORE_INDEX].green = (((long) fore->Green ()) << 8); + itemColors[wxFORE_INDEX].blue = (((long) fore->Blue ()) << 8); + itemColors[wxFORE_INDEX].flags = DoRed | DoGreen | DoBlue; + if (result == wxNO_COLORS) + result = wxFORE_COLORS; + } + + Display *dpy = display; + Colormap cmap = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dpy); + + if (back) + { + /* 5 Colours to allocate */ + for (int i = 0; i < 5; i++) + if (!YAllocColor (dpy, cmap, &itemColors[i])) + result = wxNO_COLORS; + } + else if (fore) + { + /* Only 1 colour to allocate */ + if (!YAllocColor (dpy, cmap, &itemColors[wxFORE_INDEX])) + result = wxNO_COLORS; + } + + return (result); + +} + +void wxWindow::ChangeColour(WXWidget widget) +{ + // TODO +#if 0 + int change; + + // TODO: how to determine whether we can change this item's colours? + // We used to have wxUSER_COLOURS. Now perhaps we assume we always + // can change it. + // if (!(parent->GetWindowStyleFlag() & wxUSER_COLOURS)) + // return; + + change = wxComputeColors (XtDisplay((Widget)widget), panel->GetBackgroundColour(), + panel->GetLabelColour()); + if (change == wxBACK_COLORS) + XtVaSetValues ((Widget) widget, + XmNbackground, itemColors[wxBACK_INDEX].pixel, + XmNtopShadowColor, itemColors[wxTOPS_INDEX].pixel, + XmNbottomShadowColor, itemColors[wxBOTS_INDEX].pixel, + XmNforeground, itemColors[wxFORE_INDEX].pixel, + NULL); + else if (change == wxFORE_COLORS) + XtVaSetValues (formWidget, + XmNforeground, itemColors[wxFORE_INDEX].pixel, + NULL); + + change = wxComputeColors (XtDisplay((Widget)formWidget), GetBackgroundColour(), GetLabelColour()); + if (change == wxBACK_COLORS) + XtVaSetValues (labelWidget, + XmNbackground, itemColors[wxBACK_INDEX].pixel, + XmNtopShadowColor, itemColors[wxTOPS_INDEX].pixel, + XmNbottomShadowColor, itemColors[wxBOTS_INDEX].pixel, + XmNarmColor, itemColors[wxSELE_INDEX].pixel, + XmNforeground, itemColors[wxFORE_INDEX].pixel, + NULL); + else if (change == wxFORE_COLORS) + XtVaSetValues (labelWidget, + XmNforeground, itemColors[wxFORE_INDEX].pixel, + NULL); +#endif +} + +void wxWindow::ChangeFont(WXWidget widget) +{ + /* TODO + if (widget && GetFont() && GetFont()->IsOk()) + XtVaSetValues ((Widget) widget, + XmNfontList, GetFont()->GetInternalFont (), + NULL); + */ +} diff --git a/src/stubs/wave.cpp b/src/stubs/wave.cpp index eb3a2603ad..c25681858c 100644 --- a/src/stubs/wave.cpp +++ b/src/stubs/wave.cpp @@ -18,12 +18,12 @@ #include "wx/stubs/wave.h" wxWave::wxWave() - : m_waveLength(0), m_isResource(FALSE), m_waveData(NULL) + : m_waveData(NULL), m_waveLength(0), m_isResource(FALSE) { } wxWave::wxWave(const wxString& sFileName, bool isResource) - : m_waveLength(0), m_isResource(isResource), m_waveData(NULL) + : m_waveData(NULL), m_waveLength(0), m_isResource(FALSE) { Create(sFileName, isResource); } diff --git a/src/stubs/window.cpp b/src/stubs/window.cpp index 6a538b0e80..62937732c5 100644 --- a/src/stubs/window.cpp +++ b/src/stubs/window.cpp @@ -687,6 +687,17 @@ void wxWindow::MakeModal(bool modal) } } +// If nothing defined for this, try the parent. +// E.g. we may be a button loaded from a resource, with no callback function +// defined. +void wxWindow::OnCommand(wxWindow& win, wxCommandEvent& event) +{ + if (GetEventHandler()->ProcessEvent(event) ) + return; + if (m_windowParent) + m_windowParent->GetEventHandler()->OnCommand(win, event); +} + void wxWindow::SetConstraints(wxLayoutConstraints *c) { if (m_constraints) -- 2.45.2