-distrib/*.*
+distrib/msw/*.rsp
+distrib/msw/*.bat
docs/readme.txt
docs/install.txt
typedef void WXDisplay;
typedef void WXEvent;
typedef void* WXCursor;
+typedef void* WXPixmap;
#endif
#endif
-///////////////////////////////////////////////////////////////////////////////
-// Name: menuitem.h
-// Purpose: wxMenuItem class
-// Author: Vadim Zeitlin
-// Modified by:
-// Created: 11.11.97
-// RCS-ID: $Id$
-// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
-// Licence: wxWindows license
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef _MENUITEM_H
-#define _MENUITEM_H
-
-#ifdef __GNUG__
-#pragma interface "menuitem.h"
-#endif
-
-// ----------------------------------------------------------------------------
-// headers
-// ----------------------------------------------------------------------------
-
-#include "wx/setup.h"
-
-// an exception to the general rule that a normal header doesn't include other
-// headers - only because ownerdrw.h is not always included and I don't want
-// to write #ifdef's everywhere...
-#if USE_OWNER_DRAWN
-#include "wx/ownerdrw.h"
+#ifndef _WX_MENUITEM_H_BASE_
+#define _WX_MENUITEM_H_BASE_
+
+#if defined(__WXMSW__)
+#include "wx/msw/menuitem.h"
+#elif defined(__WXMOTIF__)
+#include "wx/motif/menuitem.h"
+#elif defined(__WXGTK__)
+#include "wx/gtk/menuitem.h"
+#elif defined(__WXQT__)
+#include "wx/qt/menuitem.h"
+#elif defined(__WXMAC__)
+#include "wx/mac/menuitem.h"
+#elif defined(__WXSTUBS__)
+#include "wx/stubs/menuitem.h"
#endif
-// ----------------------------------------------------------------------------
-// constants
-// ----------------------------------------------------------------------------
-
-// id for a separator line in the menu (invalid for normal item)
-#define ID_SEPARATOR (-1)
-
-// ----------------------------------------------------------------------------
-// wxMenuItem: an item in the menu, optionally implements owner-drawn behaviour
-// ----------------------------------------------------------------------------
-class WXDLLEXPORT wxMenuItem: public wxObject
-#if USE_OWNER_DRAWN
- , public wxOwnerDrawn
#endif
-{
-DECLARE_DYNAMIC_CLASS(wxMenuItem)
-
-public:
- // ctor & dtor
- wxMenuItem(wxMenu *pParentMenu = NULL, int id = ID_SEPARATOR,
- const wxString& strName = "", const wxString& wxHelp = "",
- bool bCheckable = FALSE, wxMenu *pSubMenu = NULL);
- virtual ~wxMenuItem();
-
- // accessors (some more are inherited from wxOwnerDrawn or are below)
- bool IsSeparator() const { return m_idItem == ID_SEPARATOR; }
- bool IsEnabled() const { return m_bEnabled; }
- bool IsChecked() const { return m_bChecked; }
-
- int GetId() const { return m_idItem; }
- const wxString& GetHelp() const { return m_strHelp; }
- wxMenu *GetSubMenu() const { return m_pSubMenu; }
-
- // operations
- void SetName(const wxString& strName) { m_strName = strName; }
- void SetHelp(const wxString& strHelp) { m_strHelp = strHelp; }
-
- void Enable(bool bDoEnable = TRUE);
- void Check(bool bDoCheck = TRUE);
-
- void DeleteSubMenu();
-
-private:
- int m_idItem; // numeric id of the item
- wxString m_strHelp; // associated help string
- wxMenu *m_pSubMenu, // may be NULL
- *m_pParentMenu; // menu this item is contained in
- bool m_bEnabled, // enabled or greyed?
- m_bChecked; // checked? (only if checkable)
-
-#if USE_OWNER_DRAWN
- // wxOwnerDrawn base class already has these variables - nothing to do
-
-#else //!owner drawn
- bool m_bCheckable; // can be checked?
- wxString m_strName; // name or label of the item
-
-public:
- const wxString& GetName() const { return m_strName; }
- bool IsCheckable() const { return m_bCheckable; }
-#endif //owner drawn
-};
-
-#endif //_MENUITEM_H
\ No newline at end of file
+ // _WX_MENUITEM_H_BASE_
//// Motif-specific
WXWidget GetMenuBarWidget() const ;
- WXWidget GetShellWidget() const { return m_frameShell; }
- WXWidget GetWorkAreaWidget() const { return m_workArea; }
- WXWidget GetClientAreaWidget() const { return m_clientArea; }
+ inline WXWidget GetShellWidget() const { return m_frameShell; }
+ inline WXWidget GetWorkAreaWidget() const { return m_workArea; }
+ inline WXWidget GetClientAreaWidget() const { return m_clientArea; }
+
+ // The widget that can have children on it
+ WXWidget GetClientWidget() const;
bool GetVisibleStatus() const { return m_visibleStatus; }
bool PreResize();
//// Motif-specific
inline WXWidget GetButtonWidget() const { return m_buttonWidget; }
+ inline void SetButtonWidget(WXWidget buttonWidget) { m_buttonWidget = buttonWidget; }
inline WXWidget GetMainWidget() const { return m_menuWidget; }
+ inline wxMenu* GetParent() const { return m_menuParent; }
+ inline int GetId() const { return m_menuId; }
+ inline void SetId(int id) { m_menuId = id; }
+ inline void SetMenuBar(wxMenuBar* menuBar) { m_menuBar = menuBar; }
+ inline wxMenuBar* GetMenuBar() const { return m_menuBar; }
+
+ void CreatePopup (WXWidget logicalParent, int x, int y);
+ void DestroyPopup (void);
+ void ShowPopup (int x, int y);
+ void HidePopup (void);
+
+ WXWidget CreateMenu(wxMenuBar *menuBar, WXWidget parent, wxMenu *topMenu,
+ const wxString& title = "", bool isPulldown = FALSE);
+
+ // For popups, need to destroy, then recreate menu for a different (or
+ // possibly same) window, since the parent may change.
+ void DestroyMenu(bool full);
+ WXWidget FindMenuItem(int id, wxMenuItem **it = NULL) const;
+
public:
wxFunction m_callback;
WXWidget m_popupShell; // For holding the popup shell widget
WXWidget m_buttonWidget; // The actual string, so we can grey it etc.
int m_menuId;
- wxMenu* m_topMenu ;
+ wxMenu* m_topLevelMenu ;
wxMenu* m_menuParent;
bool m_ownedByMenuBar;
};
inline int GetMenuCount() const { return m_menuCount; }
inline wxMenu* GetMenu(int i) const { return m_menus[i]; }
+ //// Motif-specific
+ inline wxFrame* GetMenuBarFrame() const { return m_menuBarFrame; }
+ inline void SetMenuBarFrame(wxFrame* frame) { m_menuBarFrame = frame; }
+ inline WXWidget GetMainWidget() const { return m_mainWidget; }
+ inline void SetMainWidget(WXWidget widget) { m_mainWidget = widget; }
+
public:
wxEvtHandler * m_eventHandler;
int m_menuCount;
wxMenu ** m_menus;
wxString * m_titles;
wxFrame * m_menuBarFrame;
-/* TODO: data that represents the actual menubar when created.
- */
+
+ //// Motif-specific
+ WXWidget m_mainWidget;
+
};
#endif // _WX_MENU_H_
extern void wxDeleteWindowFromTable(Widget w);
extern wxWindow *wxGetWindowFromTable(Widget w);
extern bool wxAddWindowToTable(Widget w, wxWindow *win);
+extern char wxFindMnemonic(const char* s);
+extern char * wxFindAccelerator (char *s);
+extern XmString wxFindAcceleratorText (char *s);
+extern int wxCharCodeXToWX(KeySym keySym);
+extern KeySym wxCharCodeWXToX(int id);
#endif
// _WX_PRIVATE_H_
// to the window via validators.
virtual void InitDialog();
- /// MOTIF-specific
+ /// Motif-specific
+
+ void CanvasGetSize(int* width, int* height) const; // If have drawing area
+ void CanvasGetClientSize(int *width, int *height) const;
+ void CanvasGetPosition(int *x, int *y) const; // If have drawing area
+ void CanvasSetClientSize(int width, int size);
+ void CanvasSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO);
// Gives window a chance to do something in response to a size
// message, e.g. arrange status bar, toolbar etc.
// Get main widget for this window
virtual WXWidget GetMainWidget() const;
+ // Get the client widget for this window (something we can
+ // create other windows on)
+ virtual WXWidget GetClientWidget() const;
virtual void SetMainWidget(WXWidget w) { m_mainWidget = w; }
// Get the underlying X window and display
virtual WXWindow GetXWindow() const;
virtual WXDisplay *GetXDisplay() const;
+ // Generates a paint event
+ virtual void DoPaint();
+
////////////////////////////////////////////////////////////////////////
//// PROTECTED DATA
protected:
int m_returnCode;
public:
- /// MOTIF-specific
+ /// Motif-specific
bool m_button1Pressed;
bool m_button2Pressed;
bool m_button3Pressed;
-
+ // For double-click detection
+ long m_lastTS; // last timestamp
+ int m_lastButton; // last pressed button
+ wxList m_updateRects; // List of wxRectangles representing damaged region
protected:
WXWidget m_mainWidget;
+ WXWidget m_hScrollBar;
+ WXWidget m_vScrollBar;
+ WXWidget m_borderWidget;
+ WXWidget m_scrolledWindow;
+ WXWidget m_drawingArea;
bool m_winCaptured;
bool m_isShown;
+ bool m_hScroll;
+ bool m_vScroll;
+ bool m_hScrollingEnabled;
+ bool m_vScrollingEnabled;
+ WXPixmap m_backingPixmap;
+ int m_pixmapWidth;
+ int m_pixmapHeight;
+ int m_pixmapOffsetX;
+ int m_pixmapOffsetY;
DECLARE_EVENT_TABLE()
};
void wxFrame::PositionStatusBar()
{
+ if (!m_frameStatusBar)
+ return;
+
int w, h;
GetClientSize(&w, &h);
int sw, sh;
// Since we wish the status bar to be directly under the client area,
// we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.
- m_frameStatusBar->SetSize(0, h, w, sh);
+ m_frameStatusBar->SetSize(0-sh, h, w, sh);
}
WXWidget wxFrame::GetMenuBarWidget() const
{
- /* TODO
if (GetMenuBar())
return GetMenuBar()->GetMainWidget();
else
- */
return (WXWidget) NULL;
}
m_frameMenuBar = menuBar;
- // TODO
-#if 0
Widget menuBarW = XmCreateMenuBar ((Widget) m_frameWidget, "MenuBar", NULL, 0);
m_frameMenuBar->SetMainWidget( (WXWidget) menuBarW);
for (i = 0; i < menuBar->GetMenuCount(); i++)
{
wxMenu *menu = menuBar->GetMenu(i);
- menu->SetButtonWidget(menu->CreateMenu (menuBar, menuBarW, menu, menuBar->m_titles[i], TRUE);
+ wxString title(menuBar->m_titles[i]);
+ menu->SetButtonWidget(menu->CreateMenu (menuBar, menuBarW, menu, title, TRUE));
/*
* COMMENT THIS OUT IF YOU DON'T LIKE A RIGHT-JUSTIFIED HELP MENU
*/
- wxStripMenuCodes (menuBar->m_titles[i], wxBuffer);
+ wxStripMenuCodes ((char*) (const char*) title, wxBuffer);
if (strcmp (wxBuffer, "Help") == 0)
XtVaSetValues ((Widget) menuBarW, XmNmenuHelpWidget, (Widget) menu->GetButtonWidget(), NULL);
XtRealizeWidget ((Widget) menuBarW);
XtManageChild ((Widget) menuBarW);
menuBar->SetMenuBarFrame(this);
-#endif
}
void wxFrame::Fit()
//// Motif-specific
bool wxFrame::PreResize()
{
- /* TODO
- // Set status line, if any
- if (status_line_exists)
- {
- Dimension clientW, clientH;
- XtVaGetValues(clientArea, XmNwidth, &clientW, XmNheight, &clientH, NULL);
- Dimension xx, yy;
- XtVaGetValues(statusLineWidget, XmNwidth, &xx, XmNheight, &yy, NULL);
-
- XtUnmanageChild(statusLineWidget);
- XtVaSetValues(statusLineWidget, XmNx, 0, XmNy, clientH - yy, XmNwidth, clientW, NULL);
-
- if (statusLineForm)
- XtVaSetValues(statusLineForm, XmNwidth, clientW, NULL);
-
- XtManageChild(statusLineWidget);
- }
-
- int width, height;
- GetSize(&width, &height);
-
- if (width == lastWidth && height == lastHeight)
- return FALSE;
- else
- {
- return TRUE;
- }
- */
+ PositionStatusBar();
return TRUE;
}
+WXWidget wxFrame::GetClientWidget() const
+{
+ return m_clientArea;
+}
+
void wxCloseFrameCallback(Widget widget, XtPointer client_data, XmAnyCallbackStruct *cbs)
{
wxFrame *frame = (wxFrame *)client_data;
#include "wx/menuitem.h"
#include "wx/log.h"
#include "wx/utils.h"
+#include "wx/app.h"
+#include "wx/frame.h"
#include <Xm/Label.h>
#include <Xm/LabelG.h>
#include <Xm/ToggleBG.h>
#include <Xm/RowColumn.h>
+#include "wx/motif/private.h"
+
// other standard headers
// ----------------------
#include <string.h>
-void wxMenuItemCallback (Widget w, XtPointer clientData,
- XtPointer ptr);
-void wxMenuItemArmCallback (Widget w, XtPointer clientData,
- XtPointer ptr);
-void wxMenuItemDisarmCallback (Widget w, XtPointer clientData,
- XtPointer ptr);
-
#if !USE_SHARED_LIBRARY
IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxEvtHandler)
IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxEvtHandler)
m_popupShell = (WXWidget) NULL;
m_buttonWidget = (WXWidget) NULL;
m_menuId = 0;
- m_topMenu = (wxMenu*) NULL;
+ m_topLevelMenu = (wxMenu*) NULL;
m_ownedByMenuBar = FALSE;
m_menuParent = (wxMenu*) NULL;
if (m_title != "")
{
- Append(-2, m_title) ;
+ Append(ID_SEPARATOR, m_title) ;
AppendSeparator() ;
}
Callback(func);
-
- // TODO create menu
}
// The wxWindow destructor will take care of deleting the submenus.
wxMenu::~wxMenu()
{
- // TODO destroy menu and children
+ if (m_menuWidget)
+ {
+ if (m_menuParent)
+ DestroyMenu(TRUE);
+ else
+ DestroyMenu(FALSE);
+ }
+
+ // Not sure if this is right
+ if (m_menuParent && m_menuBar)
+ {
+ m_menuParent = NULL;
+ // m_menuBar = NULL;
+ }
wxNode *node = m_menuItems.First();
while (node)
{
wxMenuItem *item = (wxMenuItem *)node->Data();
- // Delete child menus.
- // Beware: they must not be appended to children list!!!
- // (because order of delete is significant)
+ /*
if (item->GetSubMenu())
item->DeleteSubMenu();
+ */
wxNode *next = node->Next();
delete item;
void wxMenu::Break()
{
- // TODO
+ m_numColumns ++;
}
// function appends a new item or submenu to the menu
void wxMenu::Append(wxMenuItem *pItem)
{
- // TODO
-
wxCHECK_RET( pItem != NULL, "can't append NULL item to the menu" );
m_menuItems.Append(pItem);
+ if (m_menuWidget)
+ pItem->CreateItem (m_menuWidget, m_menuBar, m_topLevelMenu); // this is a dynamic Append
+
m_noItems++;
}
void wxMenu::AppendSeparator()
{
- // TODO
Append(new wxMenuItem(this, ID_SEPARATOR));
}
// Pullright item
-void wxMenu::Append(int Id, const wxString& label, wxMenu *SubMenu,
+// N.B.: difference between old and new code.
+// Old code stores subMenu in 'children' for later deletion,
+// as well as in m_menuItems, whereas we only store it in
+// m_menuItems here. What implications does this have?
+
+void wxMenu::Append(int id, const wxString& label, wxMenu *subMenu,
const wxString& helpString)
{
- Append(new wxMenuItem(this, Id, label, helpString, FALSE, SubMenu));
+ Append(new wxMenuItem(this, id, label, helpString, FALSE, subMenu));
+
+ subMenu->m_topLevelMenu = m_topLevelMenu;
}
// Ordinary menu item
-void wxMenu::Append(int Id, const wxString& label,
+void wxMenu::Append(int id, const wxString& label,
const wxString& helpString, bool checkable)
{
// 'checkable' parameter is useless for Windows.
- Append(new wxMenuItem(this, Id, label, helpString, checkable));
+ Append(new wxMenuItem(this, id, label, helpString, checkable));
}
void wxMenu::Delete(int id)
wxMenuItem *item;
int pos;
- for (pos = 0, node = m_menuItems.First(); node; node = node->Next(), pos++) {
+ for (pos = 0, node = m_menuItems.First(); node; node = node->Next(), pos++)
+ {
item = (wxMenuItem *)node->Data();
if (item->GetId() == id)
break;
if (!node)
return;
+ item->DestroyItem(TRUE);
+
+ // See also old code - don't know if this is needed (seems redundant).
+ /*
+ if (item->GetSubMenu()) {
+ item->subMenu->top_level_menu = item->GetSubMenu();
+ item->subMenu->window_parent = NULL;
+ children->DeleteObject(item->GetSubMenu());
+ }
+ */
+
m_menuItems.DeleteNode(node);
delete item;
-
- // TODO
}
-void wxMenu::Enable(int Id, bool Flag)
+void wxMenu::Enable(int id, bool flag)
{
- wxMenuItem *item = FindItemForId(Id);
+ wxMenuItem *item = FindItemForId(id);
wxCHECK_RET( item != NULL, "can't enable non-existing menu item" );
- item->Enable(Flag);
+ item->Enable(flag);
}
bool wxMenu::Enabled(int Id) const
item->Check(Flag);
}
-bool wxMenu::Checked(int Id) const
+bool wxMenu::Checked(int id) const
{
- wxMenuItem *item = FindItemForId(Id);
+ wxMenuItem *item = FindItemForId(id);
wxCHECK( item != NULL, FALSE );
return item->IsChecked();
void wxMenu::SetTitle(const wxString& label)
{
m_title = label ;
- // TODO
+
+ wxNode *node = m_menuItems.First ();
+ if (!node)
+ return;
+
+ wxMenuItem *item = (wxMenuItem *) node->Data ();
+ Widget widget = (Widget) item->GetButtonWidget();
+ if (!widget)
+ return;
+
+ XmString title_str = XmStringCreateSimple ((char*) (const char*) label);
+ XtVaSetValues (widget,
+ XmNlabelString, title_str,
+ NULL);
+ // TODO: should we delete title_str now?
}
const wxString wxMenu::GetTitle() const
void wxMenu::SetLabel(int id, const wxString& label)
{
- wxMenuItem *item = FindItemForId(id) ;
- if (item==NULL)
- return;
+ wxMenuItem *item = FindItemForId(id);
+ if (item == (wxMenuItem*) NULL)
+ return;
- if (item->GetSubMenu()==NULL)
- {
- // TODO
- }
- else
- {
- // TODO
- }
- item->SetName(label);
+ item->SetLabel(label);
}
-wxString wxMenu::GetLabel(int Id) const
+wxString wxMenu::GetLabel(int id) const
{
- // TODO
- return wxString("") ;
+ wxMenuItem *it = NULL;
+ WXWidget w = FindMenuItem (id, &it);
+ if (w)
+ {
+ XmString text;
+ char *s;
+ XtVaGetValues ((Widget) w,
+ XmNlabelString, &text,
+ NULL);
+
+ if (XmStringGetLtoR (text, XmSTRING_DEFAULT_CHARSET, &s))
+ {
+ wxString str(s);
+ XtFree (s);
+ return str;
+ }
+ else
+ {
+ XmStringFree (text);
+ return wxEmptyString;
+ }
+ }
+ else
+ return wxEmptyString;
}
// Finds the item id matching the given string, -1 if not found.
bool wxWindow::PopupMenu(wxMenu *menu, int x, int y)
{
- // TODO
+ Widget widget = (Widget) GetMainWidget();
+
+ /* The menuId field seems to be usused, so we'll use it to
+ indicate whether a menu is popped up or not:
+ 0: Not currently created as a popup
+ -1: Created as a popup, but not active
+ 1: Active popup.
+ */
+
+ if (menu->GetParent() && (menu->GetId() != -1))
return FALSE;
+
+ if (menu->GetMainWidget()) {
+ menu->DestroyMenu(TRUE);
+ }
+
+ wxWindow *parent = this;
+
+ menu->SetId(1); /* Mark as popped-up */
+ menu->CreateMenu(NULL, widget, menu);
+ // menu->SetParent(parent);
+ // parent->children->Append(menu); // Store menu for later deletion
+
+ Widget menuWidget = (Widget) menu->GetMainWidget();
+
+ int rootX = 0;
+ int rootY = 0;
+
+ int deviceX = x;
+ int deviceY = y;
+ /*
+ if (this->IsKindOf(CLASSINFO(wxCanvas)))
+ {
+ wxCanvas *canvas = (wxCanvas *) this;
+ deviceX = canvas->GetDC ()->LogicalToDeviceX (x);
+ deviceY = canvas->GetDC ()->LogicalToDeviceY (y);
+ }
+ */
+
+ Display *display = XtDisplay (widget);
+ Window rootWindow = RootWindowOfScreen (XtScreen((Widget)widget));
+ Window thisWindow = XtWindow (widget);
+ Window childWindow;
+ XTranslateCoordinates (display, thisWindow, rootWindow, (int) deviceX, (int) deviceY,
+ &rootX, &rootY, &childWindow);
+
+ XButtonPressedEvent event;
+ event.type = ButtonPress;
+ event.button = 1;
+
+ event.x = deviceX;
+ event.y = deviceY;
+
+ event.x_root = rootX;
+ event.y_root = rootY;
+
+ XmMenuPosition (menuWidget, &event);
+ XtManageChild (menuWidget);
+
+ return TRUE;
}
// Menu Bar
m_menus = NULL;
m_titles = NULL;
m_menuBarFrame = NULL;
-
- // TODO
}
wxMenuBar::wxMenuBar(int n, wxMenu *menus[], const wxString titles[])
for ( i = 0; i < n; i++ )
m_titles[i] = titles[i];
m_menuBarFrame = NULL;
-
- // TODO
}
wxMenuBar::~wxMenuBar()
}
delete[] m_menus;
delete[] m_titles;
-
- // TODO
}
// Must only be used AFTER menu has been attached to frame,
wxMenuItem *item = FindItemForId(id, &itemMenu) ;
if (!item)
return;
-
- // TODO
+ item->Enable(flag);
}
void wxMenuBar::EnableTop(int pos, bool flag)
if (!item->IsCheckable())
return ;
- // TODO
+ item->Check(flag);
}
bool wxMenuBar::Checked(int id) const
if (!item)
return FALSE;
- // TODO
- return FALSE;
+ return item->IsChecked();
}
bool wxMenuBar::Enabled(int id) const
if (!item)
return FALSE;
- // TODO
- return FALSE ;
+ return item->IsEnabled();
}
-
void wxMenuBar::SetLabel(int id, const wxString& label)
{
wxMenu *itemMenu = NULL;
if (!item)
return;
- // TODO
+ item->SetLabel(label);
}
wxString wxMenuBar::GetLabel(int id) const
if (!item)
return wxString("");
- // TODO
- return wxString("") ;
+ return item->GetLabel();
}
void wxMenuBar::SetLabelTop(int pos, const wxString& label)
{
- // TODO
+ wxASSERT( (pos < m_menuCount) );
+
+ Widget w = (Widget) m_menus[pos]->GetButtonWidget();
+ if (w)
+ {
+ XmString label_str = XmStringCreateSimple ((char*) (const char*) label);
+ XtVaSetValues (w,
+ XmNlabelString, label_str,
+ NULL);
+ XmStringFree (label_str);
+ }
}
wxString wxMenuBar::GetLabelTop(int pos) const
{
- // TODO
- return wxString("");
+ wxASSERT( (pos < m_menuCount) );
+
+ Widget w = (Widget) m_menus[pos]->GetButtonWidget();
+ if (w)
+ {
+ XmString text;
+ char *s;
+ XtVaGetValues (w,
+ XmNlabelString, &text,
+ NULL);
+
+ if (XmStringGetLtoR (text, XmSTRING_DEFAULT_CHARSET, &s))
+ {
+ wxString str(s);
+ XtFree (s);
+ return str;
+ }
+ else
+ {
+ return wxEmptyString;
+ }
+ }
+ else
+ return wxEmptyString;
+
}
-bool wxMenuBar::OnDelete(wxMenu *a_menu, int pos)
+bool wxMenuBar::OnDelete(wxMenu *menu, int pos)
{
- // TODO
- return FALSE;
+ // Only applies to dynamic deletion (when set in frame)
+ if (!m_menuBarFrame)
+ return TRUE;
+
+ menu->DestroyMenu(TRUE);
+ return TRUE;
}
-bool wxMenuBar::OnAppend(wxMenu *a_menu, const char *title)
+bool wxMenuBar::OnAppend(wxMenu *menu, const char *title)
{
- // TODO
- return FALSE;
+ // Only applies to dynamic append (when set in frame)
+ if (!m_menuBarFrame)
+ return TRUE;
+
+ // Probably should be an assert here
+ if (menu->GetParent())
+ return FALSE;
+
+ // Has already been appended
+ if (menu->GetButtonWidget())
+ return FALSE;
+
+ WXWidget w = menu->CreateMenu(this, GetMainWidget(), menu, title, TRUE);
+ menu->SetButtonWidget(w);
+
+ return TRUE;
}
void wxMenuBar::Append (wxMenu * menu, const wxString& title)
m_menus[m_menuCount - 1] = (wxMenu *)menu;
m_titles[m_menuCount - 1] = title;
- // TODO
+ menu->SetMenuBar(this);
+ menu->SetParent(this);
}
void wxMenuBar::Delete(wxMenu * menu, int i)
if (!OnDelete(menu, ii))
return;
- menu->SetParent(NULL);
+ menu->SetParent((wxEvtHandler*) NULL);
-- m_menuCount;
for (j = ii; j < m_menuCount; j++)
return -1;
}
-wxMenuItem *wxMenuBar::FindItemForId (int Id, wxMenu ** itemMenu) const
+wxMenuItem *wxMenuBar::FindItemForId (int id, wxMenu ** itemMenu) const
{
if (itemMenu)
*itemMenu = NULL;
wxMenuItem *item = NULL;
int i;
for (i = 0; i < m_menuCount; i++)
- if ((item = m_menus[i]->FindItemForId (Id, itemMenu)))
+ if ((item = m_menus[i]->FindItemForId (id, itemMenu)))
return item;
return NULL;
}
-void wxMenuBar::SetHelpString (int Id, const wxString& helpString)
+void wxMenuBar::SetHelpString (int id, const wxString& helpString)
{
int i;
for (i = 0; i < m_menuCount; i++)
{
- if (m_menus[i]->FindItemForId (Id))
+ if (m_menus[i]->FindItemForId (id))
{
- m_menus[i]->SetHelpString (Id, helpString);
+ m_menus[i]->SetHelpString (id, helpString);
return;
}
}
}
-wxString wxMenuBar::GetHelpString (int Id) const
+wxString wxMenuBar::GetHelpString (int id) const
{
int i;
for (i = 0; i < m_menuCount; i++)
{
- if (m_menus[i]->FindItemForId (Id))
- return wxString(m_menus[i]->GetHelpString (Id));
+ if (m_menus[i]->FindItemForId (id))
+ return wxString(m_menus[i]->GetHelpString (id));
}
return wxString("");
}
+//// Motif-specific
+
+extern wxApp *wxTheApp;
+static XtWorkProcId WorkProcMenuId;
+
+/* Since PopupMenu under Motif stills grab right mouse button events
+ * after it was closed, we need to delete the associated widgets to
+ * allow next PopUpMenu to appear...
+ */
+
+int PostDeletionOfMenu( XtPointer* clientData )
+{
+ XtRemoveWorkProc(WorkProcMenuId);
+ wxMenu *menu = (wxMenu *)clientData;
+
+ if (menu->GetMainWidget()) {
+ wxList& list = menu->GetParent()->GetItems();
+ list.DeleteObject(menu);
+ menu->DestroyMenu(TRUE);
+ }
+ /* Mark as no longer popped up */
+ menu->m_menuId = -1;
+ return TRUE;
+}
+
+void
+wxMenuPopdownCallback(Widget w, XtPointer clientData,
+ XtPointer ptr)
+{
+ wxMenu *menu = (wxMenu *)clientData;
+
+ // Added by JOREL Jean-Charles <jjorel@silr.ireste.fr>
+ /* Since Callbacks of MenuItems are not yet processed, we put a
+ * background job which will be done when system will be idle.
+ * What awful hack!! :(
+ */
+
+ WorkProcMenuId = XtAppAddWorkProc(
+ (XtAppContext) wxTheApp->GetAppContext(),
+ (XtWorkProc) PostDeletionOfMenu,
+ (XtPointer) menu );
+ // Apparently not found in Motif headers
+ // XtVaSetValues( w, XmNpopupEnabled, XmPOPUP_DISABLED, NULL );
+}
+
+/*
+ * Create a popup or pulldown menu.
+ * Submenus of a popup will be pulldown.
+ *
+ */
+
+WXWidget wxMenu::CreateMenu (wxMenuBar * menuBar, WXWidget parent, wxMenu * topMenu, const wxString& title, bool pullDown)
+{
+ Widget menu = (Widget) 0;
+ Widget buttonWidget = (Widget) 0;
+ Arg args[5];
+ XtSetArg (args[0], XmNnumColumns, m_numColumns);
+ XtSetArg (args[1], XmNpacking, XmPACK_COLUMN);
+
+ if (!pullDown)
+ {
+ menu = XmCreatePopupMenu ((Widget) parent, "popup", args, 2);
+ XtAddCallback(menu,
+ XmNunmapCallback,
+ (XtCallbackProc)wxMenuPopdownCallback,
+ (XtPointer)this);
+ }
+ else
+ {
+ char mnem = wxFindMnemonic (title);
+ wxStripMenuCodes ((char*) (const char*) title, wxBuffer);
+
+ menu = XmCreatePulldownMenu ((Widget) parent, "pulldown", args, 2);
+
+ XmString label_str = XmStringCreateSimple (wxBuffer);
+ buttonWidget = XtVaCreateManagedWidget (wxBuffer,
+#if USE_GADGETS
+ xmCascadeButtonGadgetClass, (Widget) parent,
+#else
+ xmCascadeButtonWidgetClass, (Widget) parent,
+#endif
+ XmNlabelString, label_str,
+ XmNsubMenuId, menu,
+ NULL);
+
+ if (mnem != 0)
+ XtVaSetValues (buttonWidget, XmNmnemonic, mnem, NULL);
+
+ XmStringFree (label_str);
+ }
+
+ m_menuWidget = (WXWidget) menu;
+
+ m_menuBar = menuBar;
+ m_topLevelMenu = topMenu;
+
+ for (wxNode * node = m_menuItems.First (); node; node = node->Next ())
+ {
+ wxMenuItem *item = (wxMenuItem *) node->Data ();
+ item->CreateItem (menu, menuBar, topMenu);
+ }
+
+ return buttonWidget;
+}
+
+// Destroys the Motif implementation of the menu,
+// but maintains the wxWindows data structures so we can
+// do a CreateMenu again.
+void wxMenu::DestroyMenu (bool full)
+{
+ for (wxNode * node = m_menuItems.First (); node; node = node->Next ())
+ {
+ wxMenuItem *item = (wxMenuItem *) node->Data ();
+ item->SetMenuBar((wxMenuBar*) NULL);
+
+ item->DestroyItem(full);
+ } // for()
+
+ if (m_buttonWidget)
+ {
+ if (full)
+ {
+ XtVaSetValues((Widget) m_buttonWidget, XmNsubMenuId, NULL, NULL);
+ XtDestroyWidget ((Widget) m_buttonWidget);
+ m_buttonWidget = (WXWidget) 0;
+ }
+ }
+ if (m_menuWidget && full)
+ {
+ XtDestroyWidget((Widget) m_menuWidget);
+ m_menuWidget = (WXWidget) NULL;
+ }
+}
+
+WXWidget wxMenu::FindMenuItem (int id, wxMenuItem ** it) const
+{
+ if (id == m_menuId)
+ {
+ if (it)
+ *it = (wxMenuItem*) NULL;
+ return m_buttonWidget;
+ }
+ for (wxNode * node = m_menuItems.First (); node; node = node->Next ())
+ {
+ wxMenuItem *item = (wxMenuItem *) node->Data ();
+ if (item->GetId() == id)
+ {
+ if (it)
+ *it = item;
+ return item->GetButtonWidget();
+ }
+
+ if (item->GetSubMenu())
+ {
+ WXWidget w = item->GetSubMenu()->FindMenuItem (id, it);
+ if (w)
+ {
+ return w;
+ }
+ }
+ } // for()
+
+ if (it)
+ *it = (wxMenuItem*) NULL;
+ return (WXWidget) NULL;
+}
#include "wx/menu.h"
#include "wx/menuitem.h"
+#include "wx/utils.h"
+#include "wx/frame.h"
+
+#include <Xm/Label.h>
+#include <Xm/LabelG.h>
+#include <Xm/CascadeBG.h>
+#include <Xm/CascadeB.h>
+#include <Xm/SeparatoG.h>
+#include <Xm/PushBG.h>
+#include <Xm/ToggleB.h>
+#include <Xm/ToggleBG.h>
+#include <Xm/RowColumn.h>
+
+#include "wx/motif/private.h"
+
+void wxMenuItemCallback (Widget w, XtPointer clientData,
+ XtPointer ptr);
+void wxMenuItemArmCallback (Widget w, XtPointer clientData,
+ XtPointer ptr);
+void wxMenuItemDisarmCallback (Widget w, XtPointer clientData,
+ XtPointer ptr);
// ============================================================================
// implementation
const wxString& strName, const wxString& strHelp,
bool bCheckable,
wxMenu *pSubMenu) :
+ m_strHelp(strHelp),
m_bCheckable(bCheckable),
- m_strName(strName),
- m_strHelp(strHelp)
+ m_strName(strName)
{
wxASSERT( pParentMenu != NULL );
m_pSubMenu = pSubMenu;
m_idItem = id;
m_bEnabled = TRUE;
+
+ //// Motif-specific
+ m_menuBar = NULL;
+ m_buttonWidget = (WXWidget) NULL;
+ m_topMenu = NULL;
}
wxMenuItem::~wxMenuItem()
void wxMenuItem::Enable(bool bDoEnable)
{
- if ( m_bEnabled != bDoEnable ) {
- if ( m_pSubMenu == NULL ) { // normal menu item
- // TODO
+ if ( m_bEnabled != bDoEnable )
+ {
+ if ( m_pSubMenu == NULL )
+ { // normal menu item
+ if (m_buttonWidget)
+ XtSetSensitive( (Widget) m_buttonWidget, (Boolean) bDoEnable);
}
else // submenu
{
- // TODO
+ // Maybe we should apply this to all items in the submenu?
+ // Or perhaps it works anyway.
+ if (m_buttonWidget)
+ XtSetSensitive( (Widget) m_buttonWidget, (Boolean) bDoEnable);
}
m_bEnabled = bDoEnable;
{
wxCHECK_RET( IsCheckable(), "only checkable items may be checked" );
- if ( m_bChecked != bDoCheck ) {
- // TODO
+ if ( m_bChecked != bDoCheck )
+ {
+ if (m_buttonWidget && XtIsSubclass ((Widget) m_buttonWidget, xmToggleButtonGadgetClass))
+ {
+ XtVaSetValues ( (Widget) m_buttonWidget, XmNset, (Boolean) bDoCheck, NULL);
+ }
m_bChecked = bDoCheck;
}
-}
\ No newline at end of file
+}
+
+//// Motif-specific
+
+void wxMenuItem::CreateItem (WXWidget menu, wxMenuBar * menuBar, wxMenu * topMenu)
+{
+ m_menuBar = menuBar;
+ m_topMenu = topMenu;
+
+ if (GetId() == -2)
+ {
+ // Id=-2 identifies a Title item.
+ wxStripMenuCodes ((char*) (const char*) m_strName, wxBuffer);
+ m_buttonWidget = (WXWidget) XtVaCreateManagedWidget (wxBuffer,
+ xmLabelGadgetClass, (Widget) menu, NULL);
+ }
+ else if ((!m_strName.IsNull() && m_strName != "") && (!m_pSubMenu))
+ {
+ wxStripMenuCodes ((char*) (const char*) m_strName, wxBuffer);
+ if (IsCheckable())
+ {
+ m_buttonWidget = (WXWidget) XtVaCreateManagedWidget (wxBuffer,
+ xmToggleButtonGadgetClass, (Widget) menu,
+ NULL);
+ XtVaSetValues ((Widget) m_buttonWidget, XmNset, (Boolean) IsChecked(), NULL);
+ }
+ else
+ m_buttonWidget = (WXWidget) XtVaCreateManagedWidget (wxBuffer,
+ xmPushButtonGadgetClass, (Widget) menu,
+ NULL);
+ char mnem = wxFindMnemonic (m_strName);
+ if (mnem != 0)
+ XtVaSetValues ((Widget) m_buttonWidget, XmNmnemonic, mnem, NULL);
+
+ //// TODO: proper accelerator treatment. What does wxFindAccelerator
+ //// look for?
+ strcpy(wxBuffer, (char*) (const char*) m_strName);
+ char *accel = wxFindAccelerator (wxBuffer);
+ if (accel)
+ XtVaSetValues ((Widget) m_buttonWidget, XmNaccelerator, accel, NULL);
+
+ // TODO: What does this do?
+ strcpy(wxBuffer, (char*) (const char*) m_strName);
+ XmString accel_str = wxFindAcceleratorText (wxBuffer);
+ if (accel_str)
+ {
+ XtVaSetValues ((Widget) m_buttonWidget, XmNacceleratorText, accel_str, NULL);
+ XmStringFree (accel_str);
+ }
+
+ if (IsCheckable())
+ XtAddCallback ((Widget) m_buttonWidget,
+ XmNvalueChangedCallback,
+ (XtCallbackProc) wxMenuItemCallback,
+ (XtPointer) this);
+ else
+ XtAddCallback ((Widget) m_buttonWidget,
+ XmNactivateCallback,
+ (XtCallbackProc) wxMenuItemCallback,
+ (XtPointer) this);
+ XtAddCallback ((Widget) m_buttonWidget,
+ XmNarmCallback,
+ (XtCallbackProc) wxMenuItemArmCallback,
+ (XtPointer) this);
+ XtAddCallback ((Widget) m_buttonWidget,
+ XmNdisarmCallback,
+ (XtCallbackProc) wxMenuItemDisarmCallback,
+ (XtPointer) this);
+ }
+ else if (GetId() == -1)
+ {
+ m_buttonWidget = (WXWidget) XtVaCreateManagedWidget ("separator",
+ xmSeparatorGadgetClass, (Widget) menu, NULL);
+ }
+ else if (m_pSubMenu)
+ {
+ m_buttonWidget = m_pSubMenu->CreateMenu (menuBar, menu, topMenu, m_strName, TRUE);
+ m_pSubMenu->SetButtonWidget(m_buttonWidget);
+ XtAddCallback ((Widget) m_buttonWidget,
+ XmNcascadingCallback,
+ (XtCallbackProc) wxMenuItemArmCallback,
+ (XtPointer) this);
+ }
+ if (m_buttonWidget)
+ XtSetSensitive ((Widget) m_buttonWidget, (Boolean) IsEnabled());
+}
+
+void wxMenuItem::DestroyItem(bool full)
+{
+ if (GetId() == -2)
+ {
+ ; // Nothing
+
+ }
+ else if ((!m_strName.IsNull() && (m_strName != "")) && !m_pSubMenu)
+ {
+ if (m_buttonWidget)
+ {
+ if (IsCheckable())
+ XtRemoveCallback ((Widget) m_buttonWidget, XmNvalueChangedCallback,
+ wxMenuItemCallback, (XtPointer) this);
+ else
+ XtRemoveCallback ((Widget) m_buttonWidget, XmNactivateCallback,
+ wxMenuItemCallback, (XtPointer) this);
+ XtRemoveCallback ((Widget) m_buttonWidget, XmNarmCallback,
+ wxMenuItemArmCallback, (XtPointer) this);
+ XtRemoveCallback ((Widget) m_buttonWidget, XmNdisarmCallback,
+ wxMenuItemDisarmCallback, (XtPointer) this);
+ }
+ }
+ else if (GetId() == -1)
+ {
+ ; // Nothing
+
+ }
+ else if (GetSubMenu())
+ {
+ if (m_buttonWidget)
+ {
+ XtRemoveCallback ((Widget) m_buttonWidget, XmNcascadingCallback,
+ wxMenuItemArmCallback, (XtPointer) this);
+ }
+ m_pSubMenu->DestroyMenu(full);
+ if (full)
+ m_buttonWidget = NULL;
+ }
+
+ if (m_buttonWidget && full)
+ {
+ XtDestroyWidget ((Widget) m_buttonWidget);
+ m_buttonWidget = (WXWidget) 0;
+ }
+}
+
+void wxMenuItem::SetLabel(const wxString& label)
+{
+ char mnem = wxFindMnemonic (label);
+ wxStripMenuCodes ((char*) (const char*) label, wxBuffer);
+
+ m_strName = label;
+
+ if (m_buttonWidget)
+ {
+ XmString label_str = XmStringCreateSimple (wxBuffer);
+ XtVaSetValues ((Widget) m_buttonWidget,
+ XmNlabelString, label_str,
+ NULL);
+ XmStringFree (label_str);
+ if (mnem != 0)
+ XtVaSetValues ((Widget) m_buttonWidget, XmNmnemonic, mnem, NULL);
+ strcpy(wxBuffer, (char*) (const char*) label);
+ char *accel = wxFindAccelerator (wxBuffer);
+ if (accel)
+ XtVaSetValues ((Widget) m_buttonWidget, XmNaccelerator, accel, NULL);
+
+ strcpy(wxBuffer, (char*) (const char*) label);
+ XmString accel_str = wxFindAcceleratorText (wxBuffer);
+ if (accel_str)
+ {
+ XtVaSetValues ((Widget) m_buttonWidget, XmNacceleratorText, accel_str, NULL);
+ XmStringFree (accel_str);
+ }
+ }
+}
+
+void wxMenuItemCallback (Widget w, XtPointer clientData,
+ XtPointer ptr)
+{
+ wxMenuItem *item = (wxMenuItem *) clientData;
+ if (item)
+ {
+ if (item->IsCheckable())
+ {
+ Boolean isChecked = FALSE;
+ XtVaGetValues ((Widget) item->GetButtonWidget(), XmNset, & isChecked, NULL);
+ item->SetChecked(isChecked);
+ }
+ if (item->GetMenuBar() && item->GetMenuBar()->GetMenuBarFrame())
+ {
+ wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, item->GetId());
+ commandEvent.SetEventObject(item->GetMenuBar()->GetMenuBarFrame());
+
+ item->GetMenuBar()->GetMenuBarFrame()->GetEventHandler()->ProcessEvent(commandEvent);
+ }
+ else if (item->GetTopMenu())
+ {
+ wxCommandEvent event (wxEVT_COMMAND_MENU_SELECTED, item->GetId());
+ event.SetEventObject(item->GetTopMenu());
+ item->GetTopMenu()->ProcessCommand (event);
+ }
+ }
+}
+
+void
+wxMenuItemArmCallback (Widget w, XtPointer clientData,
+ XtPointer ptr)
+{
+ wxMenuItem *item = (wxMenuItem *) clientData;
+ if (item)
+ {
+ if (item->GetMenuBar() && item->GetMenuBar()->GetMenuBarFrame())
+ {
+ wxMenuEvent menuEvent(wxEVT_MENU_HIGHLIGHT, item->GetId());
+ menuEvent.SetEventObject(item->GetMenuBar()->GetMenuBarFrame());
+
+ item->GetMenuBar()->GetMenuBarFrame()->GetEventHandler()->ProcessEvent(menuEvent);
+ }
+ }
+}
+
+void
+wxMenuItemDisarmCallback (Widget w, XtPointer clientData,
+ XtPointer ptr)
+{
+ wxMenuItem *item = (wxMenuItem *) clientData;
+ if (item)
+ {
+ if (item->GetMenuBar() && item->GetMenuBar()->GetMenuBarFrame())
+ {
+ // TODO: not sure this is correct, since -1 means something
+ // special to event system
+ wxMenuEvent menuEvent(wxEVT_MENU_HIGHLIGHT, -1);
+ menuEvent.SetEventObject(item->GetMenuBar()->GetMenuBarFrame());
+
+ item->GetMenuBar()->GetMenuBarFrame()->GetEventHandler()->ProcessEvent(menuEvent);
+ }
+ }
+}
+
#include <Xm/Xm.h>
+#include "wx/motif/private.h"
+
// Get full hostname (eg. DoDo.BSn-Germany.crg.de)
bool wxGetHostName(char *buf, int maxSize)
{
{
return gs_displayName;
}
+
+// Find the letter corresponding to the mnemonic, for Motif
+char wxFindMnemonic (const char *s)
+{
+ char mnem = 0;
+ int len = strlen (s);
+ int i;
+ for (i = 0; i < len; i++)
+ {
+ if (s[i] == '&')
+ {
+ // Carefully handle &&
+ if ((i + 1) <= len && s[i + 1] == '&')
+ i++;
+ else
+ {
+ mnem = s[i + 1];
+ break;
+ }
+ }
+ }
+ return mnem;
+}
+
+char * wxFindAccelerator (char *s)
+{
+// The accelerator text is after the \t char.
+ while (*s && *s != '\t')
+ s++;
+ if (*s == '\0')
+ return (NULL);
+ s++;
+/*
+ Now we need to format it as X standard:
+
+ input output
+
+ F7 --> <Key>F7
+ Ctrl+N --> Ctrl<Key>N
+ Alt+k --> Meta<Key>k
+ Ctrl+Shift+A --> Ctrl Shift<Key>A
+
+ */
+
+ wxBuffer[0] = '\0';
+ char *tmp = copystring (s);
+ s = tmp;
+ char *p = s;
+
+ while (1)
+ {
+ while (*p && *p != '+')
+ p++;
+ if (*p)
+ {
+ *p = '\0';
+ if (wxBuffer[0])
+ strcat (wxBuffer, " ");
+ if (strcmp (s, "Alt"))
+ strcat (wxBuffer, s);
+ else
+ strcat (wxBuffer, "Meta");
+ s = p + 1;
+ p = s;
+ }
+ else
+ {
+ strcat (wxBuffer, "<Key>");
+ strcat (wxBuffer, s);
+ break;
+ }
+ }
+ delete[]tmp;
+ return wxBuffer;
+}
+
+XmString wxFindAcceleratorText (char *s)
+{
+// The accelerator text is after the \t char.
+ while (*s && *s != '\t')
+ s++;
+ if (*s == '\0')
+ return (NULL);
+ s++;
+ XmString text = XmStringCreateSimple (s);
+ return text;
+}
+
+#include <X11/keysym.h>
+
+int wxCharCodeXToWX(KeySym keySym)
+{
+ int id;
+ switch (keySym) {
+ case XK_Shift_L:
+ case XK_Shift_R:
+ id = WXK_SHIFT; break;
+ case XK_Control_L:
+ case XK_Control_R:
+ id = WXK_CONTROL; break;
+ case XK_BackSpace:
+ id = WXK_BACK; break;
+ case XK_Delete:
+ id = WXK_DELETE; break;
+ case XK_Clear:
+ id = WXK_CLEAR; break;
+ case XK_Tab:
+ id = WXK_TAB; break;
+ case XK_numbersign:
+ id = '#'; break;
+ case XK_Return:
+ id = WXK_RETURN; break;
+ case XK_Escape:
+ id = WXK_ESCAPE; break;
+ case XK_Pause:
+ case XK_Break:
+ id = WXK_PAUSE; break;
+ case XK_Num_Lock:
+ id = WXK_NUMLOCK; break;
+ case XK_Scroll_Lock:
+ id = WXK_SCROLL; break;
+
+ case XK_Home:
+ id = WXK_HOME; break;
+ case XK_End:
+ id = WXK_END; break;
+ case XK_Left:
+ id = WXK_LEFT; break;
+ case XK_Right:
+ id = WXK_RIGHT; break;
+ case XK_Up:
+ id = WXK_UP; break;
+ case XK_Down:
+ id = WXK_DOWN; break;
+ case XK_Next:
+ id = WXK_NEXT; break;
+ case XK_Prior:
+ id = WXK_PRIOR; break;
+ case XK_Menu:
+ id = WXK_MENU; break;
+ case XK_Select:
+ id = WXK_SELECT; break;
+ case XK_Cancel:
+ id = WXK_CANCEL; break;
+ case XK_Print:
+ id = WXK_PRINT; break;
+ case XK_Execute:
+ id = WXK_EXECUTE; break;
+ case XK_Insert:
+ id = WXK_INSERT; break;
+ case XK_Help:
+ id = WXK_HELP; break;
+
+ case XK_KP_Multiply:
+ id = WXK_MULTIPLY; break;
+ case XK_KP_Add:
+ id = WXK_ADD; break;
+ case XK_KP_Subtract:
+ id = WXK_SUBTRACT; break;
+ case XK_KP_Divide:
+ id = WXK_DIVIDE; break;
+ case XK_KP_Decimal:
+ id = WXK_DECIMAL; break;
+ case XK_KP_Equal:
+ id = '='; break;
+ case XK_KP_Space:
+ id = ' '; break;
+ case XK_KP_Tab:
+ id = WXK_TAB; break;
+ case XK_KP_Enter:
+ id = WXK_RETURN; break;
+ case XK_KP_0:
+ id = WXK_NUMPAD0; break;
+ case XK_KP_1:
+ id = WXK_NUMPAD1; break;
+ case XK_KP_2:
+ id = WXK_NUMPAD2; break;
+ case XK_KP_3:
+ id = WXK_NUMPAD3; break;
+ case XK_KP_4:
+ id = WXK_NUMPAD4; break;
+ case XK_KP_5:
+ id = WXK_NUMPAD5; break;
+ case XK_KP_6:
+ id = WXK_NUMPAD6; break;
+ case XK_KP_7:
+ id = WXK_NUMPAD7; break;
+ case XK_KP_8:
+ id = WXK_NUMPAD8; break;
+ case XK_KP_9:
+ id = WXK_NUMPAD9; break;
+ case XK_F1:
+ id = WXK_F1; break;
+ case XK_F2:
+ id = WXK_F2; break;
+ case XK_F3:
+ id = WXK_F3; break;
+ case XK_F4:
+ id = WXK_F4; break;
+ case XK_F5:
+ id = WXK_F5; break;
+ case XK_F6:
+ id = WXK_F6; break;
+ case XK_F7:
+ id = WXK_F7; break;
+ case XK_F8:
+ id = WXK_F8; break;
+ case XK_F9:
+ id = WXK_F9; break;
+ case XK_F10:
+ id = WXK_F10; break;
+ case XK_F11:
+ id = WXK_F11; break;
+ case XK_F12:
+ id = WXK_F12; break;
+ case XK_F13:
+ id = WXK_F13; break;
+ case XK_F14:
+ id = WXK_F14; break;
+ case XK_F15:
+ id = WXK_F15; break;
+ case XK_F16:
+ id = WXK_F16; break;
+ case XK_F17:
+ id = WXK_F17; break;
+ case XK_F18:
+ id = WXK_F18; break;
+ case XK_F19:
+ id = WXK_F19; break;
+ case XK_F20:
+ id = WXK_F20; break;
+ case XK_F21:
+ id = WXK_F21; break;
+ case XK_F22:
+ id = WXK_F22; break;
+ case XK_F23:
+ id = WXK_F23; break;
+ case XK_F24:
+ id = WXK_F24; break;
+ default:
+ id = (keySym <= 255) ? (int)keySym : -1;
+ } // switch
+ return id;
+}
+
+KeySym wxCharCodeWXToX(int id)
+{
+ KeySym keySym;
+
+ switch (id) {
+ case WXK_CANCEL: keySym = XK_Cancel; break;
+ case WXK_BACK: keySym = XK_BackSpace; break;
+ case WXK_TAB: keySym = XK_Tab; break;
+ case WXK_CLEAR: keySym = XK_Clear; break;
+ case WXK_RETURN: keySym = XK_Return; break;
+ case WXK_SHIFT: keySym = XK_Shift_L; break;
+ case WXK_CONTROL: keySym = XK_Control_L; break;
+ case WXK_MENU : keySym = XK_Menu; break;
+ case WXK_PAUSE: keySym = XK_Pause; break;
+ case WXK_ESCAPE: keySym = XK_Escape; break;
+ case WXK_SPACE: keySym = ' '; break;
+ case WXK_PRIOR: keySym = XK_Prior; break;
+ case WXK_NEXT : keySym = XK_Next; break;
+ case WXK_END: keySym = XK_End; break;
+ case WXK_HOME : keySym = XK_Home; break;
+ case WXK_LEFT : keySym = XK_Left; break;
+ case WXK_UP: keySym = XK_Up; break;
+ case WXK_RIGHT: keySym = XK_Right; break;
+ case WXK_DOWN : keySym = XK_Down; break;
+ case WXK_SELECT: keySym = XK_Select; break;
+ case WXK_PRINT: keySym = XK_Print; break;
+ case WXK_EXECUTE: keySym = XK_Execute; break;
+ case WXK_INSERT: keySym = XK_Insert; break;
+ case WXK_DELETE: keySym = XK_Delete; break;
+ case WXK_HELP : keySym = XK_Help; break;
+ case WXK_NUMPAD0: keySym = XK_KP_0; break;
+ case WXK_NUMPAD1: keySym = XK_KP_1; break;
+ case WXK_NUMPAD2: keySym = XK_KP_2; break;
+ case WXK_NUMPAD3: keySym = XK_KP_3; break;
+ case WXK_NUMPAD4: keySym = XK_KP_4; break;
+ case WXK_NUMPAD5: keySym = XK_KP_5; break;
+ case WXK_NUMPAD6: keySym = XK_KP_6; break;
+ case WXK_NUMPAD7: keySym = XK_KP_7; break;
+ case WXK_NUMPAD8: keySym = XK_KP_8; break;
+ case WXK_NUMPAD9: keySym = XK_KP_9; break;
+ case WXK_MULTIPLY: keySym = XK_KP_Multiply; break;
+ case WXK_ADD: keySym = XK_KP_Add; break;
+ case WXK_SUBTRACT: keySym = XK_KP_Subtract; break;
+ case WXK_DECIMAL: keySym = XK_KP_Decimal; break;
+ case WXK_DIVIDE: keySym = XK_KP_Divide; break;
+ case WXK_F1: keySym = XK_F1; break;
+ case WXK_F2: keySym = XK_F2; break;
+ case WXK_F3: keySym = XK_F3; break;
+ case WXK_F4: keySym = XK_F4; break;
+ case WXK_F5: keySym = XK_F5; break;
+ case WXK_F6: keySym = XK_F6; break;
+ case WXK_F7: keySym = XK_F7; break;
+ case WXK_F8: keySym = XK_F8; break;
+ case WXK_F9: keySym = XK_F9; break;
+ case WXK_F10: keySym = XK_F10; break;
+ case WXK_F11: keySym = XK_F11; break;
+ case WXK_F12: keySym = XK_F12; break;
+ case WXK_F13: keySym = XK_F13; break;
+ case WXK_F14: keySym = XK_F14; break;
+ case WXK_F15: keySym = XK_F15; break;
+ case WXK_F16: keySym = XK_F16; break;
+ case WXK_F17: keySym = XK_F17; break;
+ case WXK_F18: keySym = XK_F18; break;
+ case WXK_F19: keySym = XK_F19; break;
+ case WXK_F20: keySym = XK_F20; break;
+ case WXK_F21: keySym = XK_F21; break;
+ case WXK_F22: keySym = XK_F22; break;
+ case WXK_F23: keySym = XK_F23; break;
+ case WXK_F24: keySym = XK_F24; break;
+ case WXK_NUMLOCK: keySym = XK_Num_Lock; break;
+ case WXK_SCROLL: keySym = XK_Scroll_Lock; break;
+ default: keySym = id <= 255 ? (KeySym)id : 0;
+ } // switch
+ return keySym;
+}
#endif
#include <Xm/Xm.h>
+
+#include <Xm/DrawingA.h>
+#include <Xm/ScrolledW.h>
+#include <Xm/ScrollBar.h>
+#include <Xm/Frame.h>
+#include <Xm/Label.h>
+
#include "wx/motif/private.h"
#include <string.h>
+#define SCROLL_MARGIN 4
+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);
+
+#define event_left_is_down(x) ((x)->xbutton.state & Button1Mask)
+#define event_middle_is_down(x) ((x)->xbutton.state & Button2Mask)
+#define event_right_is_down(x) ((x)->xbutton.state & Button3Mask)
+
extern wxList wxPendingDelete;
#if !USE_SHARED_LIBRARY
m_pDropTarget = NULL;
#endif
- /// MOTIF-specific
+ /// Motif-specific
m_mainWidget = (WXWidget) 0;
m_button1Pressed = FALSE;
m_button2Pressed = FALSE;
m_button3Pressed = FALSE;
m_winCaptured = FALSE;
m_isShown = TRUE;
+ m_hScrollBar = (WXWidget) 0;
+ m_vScrollBar = (WXWidget) 0;
+ m_borderWidget = (WXWidget) 0;
+ m_scrolledWindow = (WXWidget) 0;
+ m_drawingArea = (WXWidget) 0;
+ m_hScroll = FALSE;
+ m_vScroll = FALSE;
+ m_hScrollingEnabled = FALSE;
+ m_vScrollingEnabled = FALSE;
+ m_backingPixmap = (WXPixmap) 0;
+ m_pixmapWidth = 0;
+ m_pixmapHeight = 0;
+ m_pixmapOffsetX = 0;
+ m_pixmapOffsetY = 0;
+ m_lastTS = 0;
+ m_lastButton = 0;
}
// Destructor
wxWindow::~wxWindow()
{
+ //// Motif-specific
+
+ // If m_drawingArea, we're a fully-fledged window with drawing area, scrollbars etc. (what wxCanvas used to be)
+ if (m_drawingArea)
+ {
+ // Destroy children before destroying self
+ DestroyChildren();
+
+ if (m_backingPixmap)
+ XFreePixmap (XtDisplay ((Widget) GetMainWidget()), (Pixmap) m_backingPixmap);
+
+ Widget w = (Widget) m_drawingArea;
+ wxDeleteWindowFromTable(w);
+
+ if (w)
+ XtDestroyWidget(w);
+ m_mainWidget = (WXWidget) 0;
+
+ // Only if we're _really_ a canvas (not a dialog box/panel)
+ if (m_scrolledWindow)
+ {
+ wxDeleteWindowFromTable((Widget) m_scrolledWindow);
+ }
+
+ if (m_hScrollBar)
+ {
+ XtUnmanageChild ((Widget) m_hScrollBar);
+ XtDestroyWidget ((Widget) m_hScrollBar);
+ }
+ if (m_vScrollBar)
+ {
+ XtUnmanageChild ((Widget) m_vScrollBar);
+ XtDestroyWidget ((Widget) m_vScrollBar);
+ }
+ if (m_scrolledWindow)
+ {
+ XtUnmanageChild ((Widget) m_scrolledWindow);
+ XtDestroyWidget ((Widget) m_scrolledWindow);
+ }
+
+ if (m_borderWidget)
+ {
+ XtDestroyWidget ((Widget) m_borderWidget);
+ m_borderWidget = (WXWidget) 0;
+ }
+ }
+
+
+ //// Generic stuff
+
// Have to delete constraints/sizer FIRST otherwise
// sizers may try to look at deleted windows as they
// delete themselves.
m_sizerParent = NULL;
m_autoLayout = FALSE;
m_windowValidator = NULL;
-
#if USE_DRAG_AND_DROP
m_pDropTarget = NULL;
#endif
-
m_caretWidth = 0; m_caretHeight = 0;
m_caretEnabled = FALSE;
m_caretShown = FALSE;
m_maxSizeY = -1;
m_defaultItem = NULL;
m_windowParent = NULL;
+
+ // Motif-specific
+ m_mainWidget = (WXWidget) 0;
+ m_button1Pressed = FALSE;
+ m_button2Pressed = FALSE;
+ m_button3Pressed = FALSE;
+ m_winCaptured = FALSE;
+ m_isShown = TRUE;
+ m_hScrollBar = (WXWidget) 0;
+ m_vScrollBar = (WXWidget) 0;
+ m_borderWidget = (WXWidget) 0;
+ m_scrolledWindow = (WXWidget) 0;
+ m_drawingArea = (WXWidget) 0;
+ m_hScroll = FALSE;
+ m_vScroll = FALSE;
+ m_hScrollingEnabled = FALSE;
+ m_vScrollingEnabled = FALSE;
+ m_backingPixmap = (WXPixmap) 0;
+ m_pixmapWidth = 0;
+ m_pixmapHeight = 0;
+ m_pixmapOffsetX = 0;
+ m_pixmapOffsetY = 0;
+
if (!parent)
return FALSE;
else
m_windowId = id;
- // TODO: create the window
+ //// TODO: we should probably optimize by only creating a
+ //// a drawing area if we have one or more scrollbars (wxVSCROLL/wxHSCROLL).
+ //// But for now, let's simplify things by always creating the
+ //// drawing area, since otherwise the translations are different.
+
+ // New translations for getting mouse motion feedback
+ String translations =
+ "<Btn1Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
+ <Btn2Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
+ <Btn3Motion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
+ <BtnMotion>: wxCanvasMotionEvent() DrawingAreaInput() ManagerGadgetButtonMotion()\n\
+ <Btn1Down>: DrawingAreaInput() ManagerGadgetArm()\n\
+ <Btn2Down>: DrawingAreaInput() ManagerGadgetArm()\n\
+ <Btn3Down>: DrawingAreaInput() ManagerGadgetArm()\n\
+ <Btn1Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
+ <Btn2Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
+ <Btn3Up>: DrawingAreaInput() ManagerGadgetActivate()\n\
+ <Motion>: wxCanvasMotionEvent() DrawingAreaInput()\n\
+ <EnterWindow>: wxCanvasMotionEvent() DrawingAreaInput()\n\
+ <LeaveWindow>: wxCanvasMotionEvent() DrawingAreaInput()\n\
+ <Key>: DrawingAreaInput()";
+
+ XtActionsRec actions[1];
+ actions[0].string = "wxCanvasMotionEvent";
+ actions[0].proc = (XtActionProc) wxCanvasMotionEvent;
+ XtAppAddActions ((XtAppContext) wxTheApp->GetAppContext(), actions, 1);
+
+ Widget parentWidget = (Widget) parent->GetClientWidget();
+ if (style & wxBORDER)
+ m_borderWidget = (WXWidget) XtVaCreateManagedWidget ("canvasBorder",
+ xmFrameWidgetClass, parentWidget,
+ XmNshadowType, XmSHADOW_IN,
+ NULL);
+
+ m_scrolledWindow = (WXWidget) XtVaCreateManagedWidget ("scrolledWindow",
+ xmScrolledWindowWidgetClass, m_borderWidget ? (Widget) m_borderWidget : parentWidget,
+ XmNspacing, 0,
+ XmNscrollingPolicy, XmAPPLICATION_DEFINED,
+ NULL);
+
+ XtTranslations ptr;
+ m_drawingArea = (WXWidget) XtVaCreateWidget ((char*) (const char*) name,
+ xmDrawingAreaWidgetClass, (Widget) m_scrolledWindow,
+ XmNunitType, XmPIXELS,
+// XmNresizePolicy, XmRESIZE_ANY,
+ XmNresizePolicy, XmRESIZE_NONE,
+ XmNmarginHeight, 0,
+ XmNmarginWidth, 0,
+ XmNtranslations, ptr = XtParseTranslationTable (translations),
+ NULL);
+ /*
+ if (GetWindowStyleFlag() & wxOVERRIDE_KEY_TRANSLATIONS)
+ {
+ XtFree ((char *) ptr);
+ ptr = XtParseTranslationTable ("<Key>: DrawingAreaInput()");
+ XtOverrideTranslations ((Widget) m_drawingArea, ptr);
+ XtFree ((char *) ptr);
+ }
+ */
+
+ wxAddWindowToTable((Widget) m_drawingArea, this);
+ wxAddWindowToTable((Widget) m_scrolledWindow, this);
+
+ /*
+ * This order is very important in Motif 1.2.1
+ *
+ */
+
+ XtRealizeWidget ((Widget) m_scrolledWindow);
+ XtRealizeWidget ((Widget) m_drawingArea);
+ XtManageChild ((Widget) m_drawingArea);
+
+ XtOverrideTranslations ((Widget) m_drawingArea,
+ ptr = XtParseTranslationTable ("<Configure>: resize()"));
+ XtFree ((char *) ptr);
+
+ XtAddCallback ((Widget) m_drawingArea, XmNexposeCallback, (XtCallbackProc) wxCanvasRepaintProc, (XtPointer) this);
+ XtAddCallback ((Widget) m_drawingArea, XmNinputCallback, (XtCallbackProc) wxCanvasInputEvent, (XtPointer) this);
+
+ /* TODO?
+ display = XtDisplay (scrolledWindow);
+ xwindow = XtWindow (drawingArea);
+ */
+
+ XtAddEventHandler ((Widget) m_drawingArea, PointerMotionHintMask | EnterWindowMask | LeaveWindowMask | FocusChangeMask,
+ False, (XtEventHandler) wxCanvasEnterLeave, (XtPointer) this);
return TRUE;
}
// Get total size
void wxWindow::GetSize(int *x, int *y) const
{
+ if (m_drawingArea)
+ {
+ CanvasGetSize(x, y);
+ return;
+ }
+
Widget widget = (Widget) GetMainWidget();
Dimension xx, yy;
XtVaGetValues(widget, XmNwidth, &xx, XmNheight, &yy, NULL);
void wxWindow::GetPosition(int *x, int *y) const
{
+ if (m_drawingArea)
+ {
+ CanvasGetPosition(x, y);
+ return;
+ }
Widget widget = (Widget) GetMainWidget();
Position xx, yy;
XtVaGetValues(widget, XmNx, &xx, XmNy, &yy, NULL);
void wxWindow::SetSize(int x, int y, int width, int height, int sizeFlags)
{
+ if (m_drawingArea)
+ {
+ CanvasSetSize(x, y, width, height, sizeFlags);
+ return;
+ }
Widget widget = (Widget) GetMainWidget();
if (x > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
void wxWindow::SetClientSize(int width, int height)
{
+ if (m_drawingArea)
+ {
+ CanvasSetClientSize(width, height);
+ return;
+ }
+
Widget widget = (Widget) GetMainWidget();
if (width > -1)
bool wxWindow::Show(bool show)
{
+ if (show)
+ {
+ if (m_borderWidget || m_scrolledWindow)
+ {
+ XtMapWidget(m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow);
+ }
+ else
+ {
+ XtMapWidget((Widget) GetMainWidget());
+ }
+ }
+ else
+ {
+ if (m_borderWidget || m_scrolledWindow)
+ {
+ XtUnmapWidget(m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow);
+ }
+ else
+ {
+ XtUnmapWidget((Widget) GetMainWidget());
+ }
+ }
+
+ /*
Window xwin = (Window) GetXWindow();
Display *xdisp = (Display*) GetXDisplay();
if (show)
XMapWindow(xdisp, xwin);
else
XUnmapWindow(xdisp, xwin);
+ */
m_isShown = show;
}
// Coordinates relative to the window
-void wxWindow::WarpPointer (int x_pos, int y_pos)
+void wxWindow::WarpPointer (int x, int y)
{
- // TODO
+ XWarpPointer (XtDisplay((Widget) GetClientWidget()), None, XtWindow((Widget) GetClientWidget()), 0, 0, 0, 0, x, y);
}
void wxWindow::OnEraseBackground(wxEraseEvent& event)
// Get the underlying X window and display
WXWindow wxWindow::GetXWindow() const
{
- return (WXWindow) XtWindow((Widget) GetMainWidget());
+ return (WXWindow) XtWindow((Widget) GetMainWidget());
}
WXDisplay *wxWindow::GetXDisplay() const
{
- return (WXDisplay*) XtDisplay((Widget) GetMainWidget());
+ return (WXDisplay*) XtDisplay((Widget) GetMainWidget());
}
WXWidget wxWindow::GetMainWidget() const
{
- return m_mainWidget;
+ if (m_drawingArea)
+ return m_drawingArea;
+ else
+ return m_mainWidget;
+}
+
+WXWidget wxWindow::GetClientWidget() const
+{
+ if (m_drawingArea != (WXWidget) 0)
+ return m_drawingArea;
+ else
+ return m_mainWidget;
}
+void wxCanvasRepaintProc (Widget drawingArea, XtPointer clientData,
+ XmDrawingAreaCallbackStruct * cbs)
+{
+ if (!wxWidgetHashTable->Get ((long) (Widget) drawingArea))
+ return;
+
+ XEvent * event = cbs->event;
+ wxWindow * canvas = (wxWindow *) clientData;
+ Display * display = (Display *) canvas->GetXDisplay();
+ // GC gc = (GC) canvas->GetDC()->gc;
+
+ 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;
+
+ canvas->m_updateRects.Clear();
+
+ /*
+ if (canvasDC)
+ {
+ XDestroyRegion(canvasDC->onpaint_reg);
+ canvasDC->onpaint_reg = NULL;
+ }
+
+ XGCValues gc_val;
+ gc_val.clip_mask = None;
+ XChangeGC(display, gc, GCClipMask, &gc_val);
+ */
+
+ 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)
+void
+wxCanvasEnterLeave (Widget drawingArea, XtPointer clientData, XCrossingEvent * event)
+{
+ XmDrawingAreaCallbackStruct cbs;
+ XEvent ev;
+
+ //if (event->mode!=NotifyNormal)
+ // return ;
+
+// ev = *((XEvent *) event); // Causes Purify error (copying too many bytes)
+ ((XCrossingEvent &) ev) = *event;
+
+ cbs.reason = XmCR_INPUT;
+ cbs.event = &ev;
+
+ wxCanvasInputEvent (drawingArea, (XtPointer) NULL, &cbs);
+}
+
+// Fix to make it work under Motif 1.0 (!)
+void wxCanvasMotionEvent (Widget drawingArea, XButtonEvent * event)
+{
+#if XmVersion<=1000
+ XmDrawingAreaCallbackStruct cbs;
+ XEvent ev;
+
+ //ev.xbutton = *event;
+ ev = *((XEvent *) event);
+ cbs.reason = XmCR_INPUT;
+ cbs.event = &ev;
+
+ wxCanvasInputEvent (drawingArea, (XtPointer) NULL, &cbs);
+#endif
+}
+
+void wxCanvasInputEvent (Widget drawingArea, XtPointer data, XmDrawingAreaCallbackStruct * cbs)
+{
+ wxWindow *canvas = (wxWindow *) wxWidgetHashTable->Get ((long) (Widget) drawingArea);
+ XEvent local_event;
+
+ if (canvas==NULL)
+ return ;
+
+ if (cbs->reason != XmCR_INPUT)
+ return;
+
+ local_event = *(cbs->event); // We must keep a copy!
+
+ switch (local_event.xany.type)
+ {
+ case EnterNotify:
+ case LeaveNotify:
+ case ButtonPress:
+ case ButtonRelease:
+ case MotionNotify:
+ {
+ wxEventType eventType = wxEVT_NULL;
+
+ if (local_event.xany.type == EnterNotify)
+ {
+ //if (local_event.xcrossing.mode!=NotifyNormal)
+ // return ; // Ignore grab events
+ eventType = wxEVT_ENTER_WINDOW;
+// canvas->GetEventHandler()->OnSetFocus();
+ }
+ else if (local_event.xany.type == LeaveNotify)
+ {
+ //if (local_event.xcrossing.mode!=NotifyNormal)
+ // return ; // Ignore grab events
+ eventType = wxEVT_LEAVE_WINDOW;
+// canvas->GetEventHandler()->OnKillFocus();
+ }
+ else if (local_event.xany.type == MotionNotify)
+ {
+ eventType = wxEVT_MOTION;
+ if (local_event.xmotion.is_hint == NotifyHint)
+ {
+ Window root, child;
+ Display *dpy = XtDisplay (drawingArea);
+
+ XQueryPointer (dpy, XtWindow (drawingArea),
+ &root, &child,
+ &local_event.xmotion.x_root,
+ &local_event.xmotion.y_root,
+ &local_event.xmotion.x,
+ &local_event.xmotion.y,
+ &local_event.xmotion.state);
+ }
+ else
+ {
+ }
+ }
+
+ else if (local_event.xany.type == ButtonPress)
+ {
+ if (local_event.xbutton.button == Button1)
+ {
+ eventType = wxEVT_LEFT_DOWN;
+ canvas->m_button1Pressed = TRUE;
+ }
+ else if (local_event.xbutton.button == Button2)
+ {
+ eventType = wxEVT_MIDDLE_DOWN;
+ canvas->m_button2Pressed = TRUE;
+ }
+ else if (local_event.xbutton.button == Button3)
+ {
+ eventType = wxEVT_RIGHT_DOWN;
+ canvas->m_button3Pressed = TRUE;
+ }
+ }
+ else if (local_event.xany.type == ButtonRelease)
+ {
+ if (local_event.xbutton.button == Button1)
+ {
+ eventType = wxEVT_LEFT_UP;
+ canvas->m_button1Pressed = FALSE;
+ }
+ else if (local_event.xbutton.button == Button2)
+ {
+ eventType = wxEVT_MIDDLE_UP;
+ canvas->m_button2Pressed = FALSE;
+ }
+ else if (local_event.xbutton.button == Button3)
+ {
+ eventType = wxEVT_RIGHT_UP;
+ canvas->m_button3Pressed = FALSE;
+ }
+ }
+
+ wxMouseEvent wxevent (eventType);
+ wxevent.m_eventHandle = (char *) &local_event;
+
+ wxevent.m_leftDown = ((eventType == wxEVT_LEFT_DOWN)
+ || (event_left_is_down (&local_event)
+ && (eventType != wxEVT_LEFT_UP)));
+ wxevent.m_middleDown = ((eventType == wxEVT_MIDDLE_DOWN)
+ || (event_middle_is_down (&local_event)
+ && (eventType != wxEVT_MIDDLE_UP)));
+ wxevent.m_rightDown = ((eventType == wxEVT_RIGHT_DOWN)
+ || (event_right_is_down (&local_event)
+ && (eventType != wxEVT_RIGHT_UP)));
+
+ wxevent.m_shiftDown = local_event.xbutton.state & ShiftMask;
+ wxevent.m_controlDown = local_event.xbutton.state & ControlMask;
+ wxevent.m_altDown = local_event.xbutton.state & Mod3Mask;
+ wxevent.m_metaDown = local_event.xbutton.state & Mod1Mask;
+ wxevent.SetTimestamp(local_event.xbutton.time);
+
+ // Now check if we need to translate this event into a double click
+ if (TRUE) // canvas->doubleClickAllowed)
+ {
+ if (wxevent.ButtonDown())
+ {
+ long dclickTime = XtGetMultiClickTime((Display*) wxGetDisplay()) ;
+
+ // get button and time-stamp
+ int button = 0;
+ if (wxevent.LeftDown()) button = 1;
+ else if (wxevent.MiddleDown()) button = 2;
+ else if (wxevent.RightDown()) button = 3;
+ long ts = wxevent.GetTimestamp();
+ // check, if single or double click
+ if (canvas->m_lastButton && canvas->m_lastButton==button && (ts - canvas->m_lastTS) < dclickTime)
+ {
+ // I have a dclick
+ canvas->m_lastButton = 0;
+ switch ( eventType )
+ {
+ case wxEVT_LEFT_DOWN:
+ wxevent.SetEventType(wxEVT_LEFT_DCLICK);
+ break;
+ case wxEVT_MIDDLE_DOWN:
+ wxevent.SetEventType(wxEVT_MIDDLE_DCLICK);
+ break;
+ case wxEVT_RIGHT_DOWN:
+ wxevent.SetEventType(wxEVT_RIGHT_DCLICK);
+ break;
+
+ default :
+ break;
+ }
+
+ }
+ else
+ {
+ // not fast enough or different button
+ canvas->m_lastTS = ts;
+ canvas->m_lastButton = button;
+ }
+ }
+ }
+
+ wxevent.SetId(canvas->GetId());
+ wxevent.SetEventObject(canvas);
+ canvas->GetEventHandler()->ProcessEvent (wxevent);
+ /*
+ if (eventType == wxEVT_ENTER_WINDOW ||
+ eventType == wxEVT_LEAVE_WINDOW ||
+ eventType == wxEVT_MOTION
+ )
+ return;
+ */
+ break;
+ }
+ case KeyPress:
+ {
+ KeySym keySym;
+// XComposeStatus compose;
+// (void) XLookupString ((XKeyEvent *) & local_event, wxBuffer, 20, &keySym, &compose);
+ (void) XLookupString ((XKeyEvent *) & local_event, wxBuffer, 20, &keySym, NULL);
+ int id = wxCharCodeXToWX (keySym);
+
+ wxKeyEvent event (wxEVT_CHAR);
+
+ if (local_event.xkey.state & ShiftMask)
+ event.m_shiftDown = TRUE;
+ if (local_event.xkey.state & ControlMask)
+ event.m_controlDown = TRUE;
+ if (local_event.xkey.state & Mod3Mask)
+ event.m_altDown = TRUE;
+ if (local_event.xkey.state & Mod1Mask)
+ event.m_metaDown = TRUE;
+ event.SetEventObject(canvas);
+ event.m_keyCode = id;
+ event.SetTimestamp(local_event.xkey.time);
+
+ if (id > -1)
+ {
+ // Implement wxFrame::OnCharHook by checking ancestor.
+ wxWindow *parent = canvas->GetParent();
+ while (parent && !parent->IsKindOf(CLASSINFO(wxFrame)))
+ parent = parent->GetParent();
+
+ if (parent)
+ {
+ event.SetEventType(wxEVT_CHAR_HOOK);
+ if (parent->GetEventHandler()->ProcessEvent(event))
+ return;
+ event.SetEventType(wxEVT_CHAR);
+ }
+
+ canvas->GetEventHandler()->ProcessEvent (event);
+ }
+ break;
+ }
+ case FocusIn:
+ {
+ if (local_event.xfocus.detail != NotifyPointer)
+ {
+ wxFocusEvent event(wxEVT_SET_FOCUS, canvas->GetId());
+ event.SetEventObject(canvas);
+ canvas->GetEventHandler()->ProcessEvent(event);
+ }
+ break;
+ }
+ case FocusOut:
+ {
+ if (local_event.xfocus.detail != NotifyPointer)
+ {
+ wxFocusEvent event(wxEVT_KILL_FOCUS, canvas->GetId());
+ event.SetEventObject(canvas);
+ canvas->GetEventHandler()->ProcessEvent(event);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void wxWindow::DoPaint()
+{
+ //TODO : make a temporary gc so we can do the XCopyArea below
+ if (0) // m_backingPixmap)
+ {
+ /*
+ Widget drawingArea = (Widget) m_drawingArea;
+ // int orig = GetDC()->GetLogicalFunction();
+ // GetDC()->SetLogicalFunction (wxCOPY);
+
+ // TODO: it may not be necessary to store m_pixmapOffsetX/Y; we
+ // should be able to calculate them.
+ XCopyArea (XtDisplay (drawingArea), m_backingPixmap, XtWindow (drawingArea), GetDC ()->gc,
+ m_pixmapOffsetX, m_pixmapOffsetY,
+ m_pixmapWidth, m_pixmapHeight,
+ 0, 0);
+
+ // GetDC()->SetLogicalFunction (orig);
+ */
+ }
+ else
+ {
+ wxPaintEvent event(GetId());
+ event.SetEventObject(this);
+ GetEventHandler()->ProcessEvent(event);
+ }
+}
+
+// SetSize, but as per old wxCanvas (with drawing widget etc.)
+void wxWindow::CanvasSetSize (int x, int y, int w, int h, int sizeFlags)
+{
+ Widget drawingArea = (Widget) m_drawingArea;
+ bool managed = XtIsManaged(m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow);
+
+ if (managed)
+ XtUnmanageChild (m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow);
+ XtVaSetValues((Widget) m_drawingArea, XmNresizePolicy, XmRESIZE_ANY, NULL);
+
+ if (x > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
+ {
+ XtVaSetValues (m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow,
+ XmNx, x, NULL);
+ }
+
+ if (y > -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
+ {
+ XtVaSetValues (m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow,
+ XmNy, y, NULL);
+ }
+
+ if (w > -1)
+ {
+ if (m_borderWidget)
+ {
+ XtVaSetValues ((Widget) m_borderWidget, XmNwidth, w, NULL);
+ short thick, margin;
+ XtVaGetValues ((Widget) m_borderWidget,
+ XmNshadowThickness, &thick,
+ XmNmarginWidth, &margin,
+ NULL);
+ w -= 2 * (thick + margin);
+ }
+
+ XtVaSetValues ((Widget) m_scrolledWindow, XmNwidth, w, NULL);
+
+ Dimension spacing;
+ Widget sbar;
+ XtVaGetValues ((Widget) m_scrolledWindow,
+ XmNspacing, &spacing,
+ XmNverticalScrollBar, &sbar,
+ NULL);
+ Dimension wsbar;
+ if (sbar)
+ XtVaGetValues (sbar, XmNwidth, &wsbar, NULL);
+ else
+ wsbar = 0;
+
+ w -= (spacing + wsbar);
+
+ XtVaSetValues ((Widget) m_drawingArea, XmNwidth, w, NULL);
+ }
+ if (h > -1)
+ {
+ if (m_borderWidget)
+ {
+ XtVaSetValues ((Widget) m_borderWidget, XmNheight, h, NULL);
+ short thick, margin;
+ XtVaGetValues ((Widget) m_borderWidget,
+ XmNshadowThickness, &thick,
+ XmNmarginHeight, &margin,
+ NULL);
+ h -= 2 * (thick + margin);
+ }
+
+ XtVaSetValues ((Widget) m_scrolledWindow, XmNheight, h, NULL);
+
+ Dimension spacing;
+ Widget sbar;
+ XtVaGetValues ((Widget) m_scrolledWindow,
+ XmNspacing, &spacing,
+ XmNhorizontalScrollBar, &sbar,
+ NULL);
+ Dimension wsbar;
+ if (sbar)
+ XtVaGetValues (sbar, XmNheight, &wsbar, NULL);
+ else
+ wsbar = 0;
+
+ h -= (spacing + wsbar);
+
+ XtVaSetValues ((Widget) m_drawingArea, XmNheight, h, NULL);
+ }
+ if (managed)
+ XtManageChild (m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow);
+ XtVaSetValues((Widget) m_drawingArea, XmNresizePolicy, XmRESIZE_NONE, NULL);
+
+ int ww, hh;
+ GetClientSize (&ww, &hh);
+ wxSizeEvent sizeEvent(wxSize(ww, hh), GetId());
+ sizeEvent.SetEventObject(this);
+
+ GetEventHandler()->ProcessEvent(sizeEvent);
+}
+
+void wxWindow::CanvasSetClientSize (int w, int h)
+{
+ Widget drawingArea = (Widget) m_drawingArea;
+
+ XtVaSetValues((Widget) m_drawingArea, XmNresizePolicy, XmRESIZE_ANY, NULL);
+
+ if (w > -1)
+ XtVaSetValues ((Widget) m_drawingArea, XmNwidth, w, NULL);
+ if (h > -1)
+ XtVaSetValues ((Widget) m_drawingArea, XmNheight, h, NULL);
+ /* TODO: is this necessary?
+ allowRepainting = FALSE;
+
+ XSync (XtDisplay (drawingArea), FALSE);
+ XEvent event;
+ while (XtAppPending (wxTheApp->appContext))
+ {
+ XFlush (XtDisplay (drawingArea));
+ XtAppNextEvent (wxTheApp->appContext, &event);
+ XtDispatchEvent (&event);
+ }
+ */
+
+ XtVaSetValues((Widget) m_drawingArea, XmNresizePolicy, XmRESIZE_NONE, NULL);
+
+ /* TODO
+ allowRepainting = TRUE;
+ DoRefresh ();
+ */
+
+ wxSizeEvent sizeEvent(wxSize(w, h), GetId());
+ sizeEvent.SetEventObject(this);
+
+ GetEventHandler()->ProcessEvent(sizeEvent);
+}
+
+void wxWindow::CanvasGetClientSize (int *w, int *h) const
+{
+ // Must return the same thing that was set via SetClientSize
+ Dimension xx, yy;
+ XtVaGetValues ((Widget) m_drawingArea, XmNwidth, &xx, XmNheight, &yy, NULL);
+ *w = xx;
+ *h = yy;
+}
+
+void wxWindow::CanvasGetSize (int *w, int *h) const
+{
+ Dimension xx, yy;
+ if ((Widget) m_borderWidget)
+ XtVaGetValues ((Widget) m_borderWidget, XmNwidth, &xx, XmNheight, &yy, NULL);
+ else if ((Widget) m_scrolledWindow)
+ XtVaGetValues ((Widget) m_scrolledWindow, XmNwidth, &xx, XmNheight, &yy, NULL);
+ else
+ XtVaGetValues ((Widget) m_drawingArea, XmNwidth, &xx, XmNheight, &yy, NULL);
+
+ *w = xx;
+ *h = yy;
+}
+
+void wxWindow::CanvasGetPosition (int *x, int *y) const
+{
+ Position xx, yy;
+ XtVaGetValues (m_borderWidget ? (Widget) m_borderWidget : (Widget) m_scrolledWindow, XmNx, &xx, XmNy, &yy, NULL);
+ *x = xx;
+ *y = yy;
+}