Some more wxMotif stuff: menus
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@753 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
distrib/*.*
|
||||
distrib/msw/*.rsp
|
||||
distrib/msw/*.bat
|
||||
|
||||
docs/readme.txt
|
||||
docs/install.txt
|
||||
|
@@ -893,6 +893,7 @@ typedef void* WXColormap;
|
||||
typedef void WXDisplay;
|
||||
typedef void WXEvent;
|
||||
typedef void* WXCursor;
|
||||
typedef void* WXPixmap;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@@ -1,95 +1,19 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// 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 _WX_MENUITEM_H_BASE_
|
||||
#define _WX_MENUITEM_H_BASE_
|
||||
|
||||
#ifndef _MENUITEM_H
|
||||
#define _MENUITEM_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "menuitem.h"
|
||||
#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
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// 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"
|
||||
#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
|
||||
// _WX_MENUITEM_H_BASE_
|
||||
|
@@ -147,9 +147,12 @@ public:
|
||||
//// 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();
|
||||
|
@@ -90,7 +90,27 @@ public:
|
||||
|
||||
//// 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;
|
||||
|
||||
@@ -107,7 +127,7 @@ public:
|
||||
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;
|
||||
};
|
||||
@@ -157,14 +177,22 @@ class WXDLLEXPORT wxMenuBar: public wxEvtHandler
|
||||
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_
|
||||
|
@@ -23,6 +23,11 @@ extern wxHashTable *wxWidgetHashTable;
|
||||
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_
|
||||
|
@@ -448,7 +448,13 @@ public:
|
||||
// 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.
|
||||
@@ -456,12 +462,18 @@ public:
|
||||
|
||||
// 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:
|
||||
@@ -507,15 +519,32 @@ public:
|
||||
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()
|
||||
};
|
||||
|
@@ -579,6 +579,9 @@ void wxFrame::SetStatusWidths(int n, const int widths_field[])
|
||||
|
||||
void wxFrame::PositionStatusBar()
|
||||
{
|
||||
if (!m_frameStatusBar)
|
||||
return;
|
||||
|
||||
int w, h;
|
||||
GetClientSize(&w, &h);
|
||||
int sw, sh;
|
||||
@@ -586,16 +589,14 @@ void wxFrame::PositionStatusBar()
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
@@ -612,8 +613,6 @@ void wxFrame::SetMenuBar(wxMenuBar *menuBar)
|
||||
|
||||
m_frameMenuBar = menuBar;
|
||||
|
||||
// TODO
|
||||
#if 0
|
||||
Widget menuBarW = XmCreateMenuBar ((Widget) m_frameWidget, "MenuBar", NULL, 0);
|
||||
m_frameMenuBar->SetMainWidget( (WXWidget) menuBarW);
|
||||
|
||||
@@ -621,12 +620,13 @@ void wxFrame::SetMenuBar(wxMenuBar *menuBar)
|
||||
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);
|
||||
@@ -635,7 +635,6 @@ void wxFrame::SetMenuBar(wxMenuBar *menuBar)
|
||||
XtRealizeWidget ((Widget) menuBarW);
|
||||
XtManageChild ((Widget) menuBarW);
|
||||
menuBar->SetMenuBarFrame(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
void wxFrame::Fit()
|
||||
@@ -1016,37 +1015,15 @@ static void wxFrameMapProc(Widget frameShell, XtPointer clientData,
|
||||
//// 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;
|
||||
|
@@ -26,6 +26,8 @@
|
||||
#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>
|
||||
@@ -37,17 +39,12 @@
|
||||
#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)
|
||||
@@ -74,36 +71,46 @@ wxMenu::wxMenu(const wxString& title, const wxFunction func)
|
||||
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;
|
||||
@@ -114,40 +121,47 @@ wxMenu::~wxMenu()
|
||||
|
||||
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)
|
||||
@@ -156,7 +170,8 @@ 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;
|
||||
@@ -165,18 +180,27 @@ void wxMenu::Delete(int id)
|
||||
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
|
||||
@@ -195,9 +219,9 @@ void wxMenu::Check(int Id, bool Flag)
|
||||
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();
|
||||
@@ -206,7 +230,21 @@ bool wxMenu::Checked(int Id) const
|
||||
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
|
||||
@@ -216,25 +254,39 @@ 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.
|
||||
@@ -332,8 +384,66 @@ void wxMenu::ProcessCommand(wxCommandEvent & event)
|
||||
|
||||
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
|
||||
@@ -344,8 +454,6 @@ wxMenuBar::wxMenuBar()
|
||||
m_menus = NULL;
|
||||
m_titles = NULL;
|
||||
m_menuBarFrame = NULL;
|
||||
|
||||
// TODO
|
||||
}
|
||||
|
||||
wxMenuBar::wxMenuBar(int n, wxMenu *menus[], const wxString titles[])
|
||||
@@ -358,8 +466,6 @@ 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()
|
||||
@@ -371,8 +477,6 @@ wxMenuBar::~wxMenuBar()
|
||||
}
|
||||
delete[] m_menus;
|
||||
delete[] m_titles;
|
||||
|
||||
// TODO
|
||||
}
|
||||
|
||||
// Must only be used AFTER menu has been attached to frame,
|
||||
@@ -383,8 +487,7 @@ void wxMenuBar::Enable(int id, bool flag)
|
||||
wxMenuItem *item = FindItemForId(id, &itemMenu) ;
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
// TODO
|
||||
item->Enable(flag);
|
||||
}
|
||||
|
||||
void wxMenuBar::EnableTop(int pos, bool flag)
|
||||
@@ -404,7 +507,7 @@ void wxMenuBar::Check(int id, bool flag)
|
||||
if (!item->IsCheckable())
|
||||
return ;
|
||||
|
||||
// TODO
|
||||
item->Check(flag);
|
||||
}
|
||||
|
||||
bool wxMenuBar::Checked(int id) const
|
||||
@@ -414,8 +517,7 @@ bool wxMenuBar::Checked(int id) const
|
||||
if (!item)
|
||||
return FALSE;
|
||||
|
||||
// TODO
|
||||
return FALSE;
|
||||
return item->IsChecked();
|
||||
}
|
||||
|
||||
bool wxMenuBar::Enabled(int id) const
|
||||
@@ -425,11 +527,9 @@ 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;
|
||||
@@ -438,7 +538,7 @@ void wxMenuBar::SetLabel(int id, const wxString& label)
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
// TODO
|
||||
item->SetLabel(label);
|
||||
}
|
||||
|
||||
wxString wxMenuBar::GetLabel(int id) const
|
||||
@@ -449,31 +549,81 @@ 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)
|
||||
@@ -504,7 +654,8 @@ 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)
|
||||
@@ -531,7 +682,7 @@ 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++)
|
||||
@@ -558,7 +709,7 @@ int wxMenuBar::FindMenuItem (const wxString& menuString, const wxString& itemStr
|
||||
return -1;
|
||||
}
|
||||
|
||||
wxMenuItem *wxMenuBar::FindItemForId (int Id, wxMenu ** itemMenu) const
|
||||
wxMenuItem *wxMenuBar::FindItemForId (int id, wxMenu ** itemMenu) const
|
||||
{
|
||||
if (itemMenu)
|
||||
*itemMenu = NULL;
|
||||
@@ -566,33 +717,199 @@ wxMenuItem *wxMenuBar::FindItemForId (int Id, wxMenu ** itemMenu) const
|
||||
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;
|
||||
}
|
||||
|
@@ -15,6 +15,27 @@
|
||||
|
||||
#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
|
||||
@@ -39,9 +60,9 @@ wxMenuItem::wxMenuItem(wxMenu *pParentMenu, int id,
|
||||
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 );
|
||||
|
||||
@@ -49,6 +70,11 @@ wxMenuItem::wxMenuItem(wxMenu *pParentMenu, int id,
|
||||
m_pSubMenu = pSubMenu;
|
||||
m_idItem = id;
|
||||
m_bEnabled = TRUE;
|
||||
|
||||
//// Motif-specific
|
||||
m_menuBar = NULL;
|
||||
m_buttonWidget = (WXWidget) NULL;
|
||||
m_topMenu = NULL;
|
||||
}
|
||||
|
||||
wxMenuItem::~wxMenuItem()
|
||||
@@ -72,13 +98,19 @@ void wxMenuItem::DeleteSubMenu()
|
||||
|
||||
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;
|
||||
@@ -89,8 +121,240 @@ void wxMenuItem::Check(bool bDoCheck)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
//// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -28,6 +28,8 @@
|
||||
|
||||
#include <Xm/Xm.h>
|
||||
|
||||
#include "wx/motif/private.h"
|
||||
|
||||
// Get full hostname (eg. DoDo.BSn-Germany.crg.de)
|
||||
bool wxGetHostName(char *buf, int maxSize)
|
||||
{
|
||||
@@ -322,3 +324,323 @@ wxString wxGetDisplayName()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@@ -36,10 +36,27 @@
|
||||
#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
|
||||
@@ -87,18 +104,84 @@ wxWindow::wxWindow()
|
||||
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.
|
||||
@@ -174,11 +257,9 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id,
|
||||
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;
|
||||
@@ -188,6 +269,29 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id,
|
||||
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;
|
||||
|
||||
@@ -214,7 +318,92 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id,
|
||||
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;
|
||||
}
|
||||
@@ -309,6 +498,12 @@ void wxWindow::DragAcceptFiles(bool accept)
|
||||
// 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);
|
||||
@@ -317,6 +512,11 @@ void wxWindow::GetSize(int *x, int *y) const
|
||||
|
||||
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);
|
||||
@@ -377,6 +577,11 @@ void wxWindow::GetClientSize(int *x, int *y) const
|
||||
|
||||
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))
|
||||
@@ -396,6 +601,12 @@ void wxWindow::SetSize(int x, int y, int width, int height, int sizeFlags)
|
||||
|
||||
void wxWindow::SetClientSize(int width, int height)
|
||||
{
|
||||
if (m_drawingArea)
|
||||
{
|
||||
CanvasSetClientSize(width, height);
|
||||
return;
|
||||
}
|
||||
|
||||
Widget widget = (Widget) GetMainWidget();
|
||||
|
||||
if (width > -1)
|
||||
@@ -429,12 +640,37 @@ void wxWindow::AdjustForParentClientOrigin(int& x, int& y, int sizeFlags)
|
||||
|
||||
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;
|
||||
|
||||
@@ -640,9 +876,9 @@ void wxWindow::Centre(int direction)
|
||||
}
|
||||
|
||||
// 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)
|
||||
@@ -1493,17 +1729,564 @@ void wxDeleteWindowFromTable(Widget w)
|
||||
// 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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user