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:
Julian Smart
1998-09-18 21:33:46 +00:00
parent 2319d2b09a
commit 50414e24a7
12 changed files with 1893 additions and 239 deletions

View File

@@ -1,4 +1,5 @@
distrib/*.*
distrib/msw/*.rsp
distrib/msw/*.bat
docs/readme.txt
docs/install.txt

View File

@@ -893,6 +893,7 @@ typedef void* WXColormap;
typedef void WXDisplay;
typedef void WXEvent;
typedef void* WXCursor;
typedef void* WXPixmap;
#endif
#endif

View File

@@ -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_

View File

@@ -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();

View File

@@ -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_

View File

@@ -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_

View File

@@ -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()
};

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}

View File

@@ -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;
}