More-or-less finished reasonably cool wxToolBar class with tooltips.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@899 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Julian Smart 1998-10-22 14:08:14 +00:00
parent ef366d323b
commit 1a3ac83faf
8 changed files with 398 additions and 110 deletions

View File

@ -37,29 +37,19 @@ High Priority
- wxSpinButton - wxSpinButton
- wxTextCtrl text file loading and saving.
- A generic version of wxNotebook that can be used in wxMotif and - A generic version of wxNotebook that can be used in wxMotif and
other toolkits that don't have a native control. Perhaps use wxTab as a other toolkits that don't have a native control. Perhaps use wxTab as a
starting point. starting point.
- Complete the MDI implementation. Could eventually alter the MDI
widgets to be more Windows-like -- currently it's half-hearted.
- Tidy dialogs such as the colour and font selectors. - Tidy dialogs such as the colour and font selectors.
- Use generic wxTreeCtrl, wxListCtrl: debug and enhance these. - Use generic wxTreeCtrl, wxListCtrl: debug and enhance these.
- Write a better generic wxToolBar class than wxToolBarSimple.
Alternatively, write a toolbar using Motif as described here:
http://www.motifzone.com/tmd/articles/Kurt_Huhner/jun96.html.
This article also explains how to implement tooltips.
- Find out why modal dialogs give a grab warning. - Find out why modal dialogs give a grab warning.
- Find out why UI updates aren't working (probably an OnIdle failure). - wxSystemSettings. Eventually, should have control panel-like utility
to change colours/fonts but meanwhile should maybe read them
- wxSystemSettings from a file.
- wxThread (hopefully, similar to wxGTK) - wxThread (hopefully, similar to wxGTK)
@ -106,8 +96,14 @@ Low Priority
Netscape is running. See: Netscape is running. See:
http://www.motifzone.com/tmd/articles/John_Cwikla/index.html http://www.motifzone.com/tmd/articles/John_Cwikla/index.html
- wxRCConfig (a config class using X .rc files). Could simply
implement it in terms of current wxGet/WriteResource functions.
- wxCheckBoxList - wxCheckBoxList
- Reimplement combobox using Lesstif's widget (avoiding GPL'ed
widget currently used).
- Write generic wxDirDialog (directory selector) - Write generic wxDirDialog (directory selector)
- Use native Motif dialogs for wxMessageBox - Use native Motif dialogs for wxMessageBox
@ -116,3 +112,6 @@ Low Priority
Linux) Linux)
- Blit scaling - Blit scaling
- Could eventually alter the MDI widgets to be more Windows-like
-- currently it's half-hearted.

View File

@ -70,10 +70,19 @@ class WXDLLEXPORT wxToolBar: public wxToolBarBase
// necessary for completing the toolbar construction. // necessary for completing the toolbar construction.
bool Realize() { return CreateTools(); }; bool Realize() { return CreateTools(); };
// Implementation
void DestroyPixmaps();
int FindIndexForWidget(WXWidget w);
WXWidget FindWidgetForIndex(int index);
protected: protected:
// List of widgets in the toolbar, indexed by tool index // List of widgets in the toolbar, indexed by tool index
wxList m_widgets; wxList m_widgets;
// List of pixmaps to destroy when tools are recreated or
// or toolbar is destroyed.
wxList m_pixmaps;
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
}; };

View File

@ -39,8 +39,8 @@ MAKE=make
LEX=flex.exe -t -L LEX=flex.exe -t -L
# YACC. byacc or bison # YACC. byacc or bison
# YACC=byacc.exe YACC=byacc.exe
YACC=bison.exe # YACC=bison.exe
# Resource compiler # Resource compiler
RESCOMP=windres.exe RESCOMP=windres.exe

View File

@ -169,7 +169,7 @@ void wxBitmapButton::SetBitmapLabel(const wxBitmap& bitmap)
// since it is no longer valid. // since it is no longer valid.
XtVaSetValues ((Widget) m_mainWidget, XtVaSetValues ((Widget) m_mainWidget,
XmNlabelType, XmSTRING, XmNlabelType, XmSTRING,
XmNlabelPixmap, NULL, // TODO: Does this work? XmNlabelPixmap, XmUNSPECIFIED_PIXMAP,
XmNlabelInsensitivePixmap, NULL, XmNlabelInsensitivePixmap, NULL,
XmNarmPixmap, NULL, XmNarmPixmap, NULL,
NULL); NULL);

View File

@ -114,7 +114,7 @@ void wxStaticBitmap::SetBitmap(const wxBitmap& bitmap)
// since it is no longer valid. // since it is no longer valid.
XtVaSetValues (widget, XtVaSetValues (widget,
XmNlabelType, XmSTRING, XmNlabelType, XmSTRING,
XmNlabelPixmap, NULL, // TODO: Does this work? XmNlabelPixmap, XmUNSPECIFIED_PIXMAP,
NULL); NULL);
} }
} }

View File

@ -257,37 +257,36 @@ bool wxTextCtrl::LoadFile(const wxString& file)
Clear(); Clear();
ifstream input((char*) (const char*) file, ios::nocreate | ios::in); Widget textWidget = (Widget) m_mainWidget;
FILE *fp;
if (!input.bad()) struct stat statb;
if ((stat ((char*) (const char*) file, &statb) == -1) || (statb.st_mode & S_IFMT) != S_IFREG ||
!(fp = fopen ((char*) (const char*) file, "r")))
{ {
struct stat stat_buf; return FALSE;
if (stat(file, &stat_buf) < 0) }
return FALSE; else
// This may need to be a bigger buffer than the file size suggests, {
// if it's a UNIX file. Give it an extra 1000 just in case. long len = statb.st_size;
char *tmp_buffer = (char*)malloc((size_t)(stat_buf.st_size+1+1000)); char *text;
long no_lines = 0; if (!(text = XtMalloc ((unsigned) (len + 1))))
long pos = 0; {
while (!input.eof() && input.peek() != EOF) fclose (fp);
{ return FALSE;
input.getline(wxBuffer, 500); }
int len = strlen(wxBuffer); if (fread (text, sizeof (char), len, fp) != (size_t) len)
wxBuffer[len] = 13; {
wxBuffer[len+1] = 10; }
wxBuffer[len+2] = 0; fclose (fp);
strcpy(tmp_buffer+pos, wxBuffer);
pos += strlen(wxBuffer); text[len] = 0;
no_lines++; XmTextSetString (textWidget, text);
} // m_textPosition = len;
XtFree (text);
// TODO add line m_modified = FALSE;
return TRUE;
free(tmp_buffer);
return TRUE;
} }
return FALSE;
} }
// If file is null, try saved file name first // If file is null, try saved file name first
@ -301,13 +300,31 @@ bool wxTextCtrl::SaveFile(const wxString& file)
return FALSE; return FALSE;
m_fileName = theFile; m_fileName = theFile;
ofstream output((char*) (const char*) theFile); Widget textWidget = (Widget) m_mainWidget;
if (output.bad()) FILE *fp;
return FALSE;
// TODO get and save text if (!(fp = fopen ((char*) (const char*) theFile, "w")))
{
return FALSE;
}
else
{
char *text = XmTextGetString (textWidget);
long len = XmTextGetLastPosition (textWidget);
return FALSE; if (fwrite (text, sizeof (char), len, fp) != (size_t) len)
{
// Did not write whole file
}
// Make sure newline terminates the file
if (text[len - 1] != '\n')
fputc ('\n', fp);
fclose (fp);
XtFree (text);
m_modified = FALSE;
return TRUE;
}
} }
void wxTextCtrl::WriteText(const wxString& text) void wxTextCtrl::WriteText(const wxString& text)

View File

@ -55,6 +55,7 @@ wxTimer::wxTimer()
wxTimer::~wxTimer() wxTimer::~wxTimer()
{ {
Stop(); Stop();
wxTimerList.DeleteObject(this);
} }
bool wxTimer::Start(int milliseconds, bool mode) bool wxTimer::Start(int milliseconds, bool mode)

View File

@ -14,11 +14,14 @@
#endif #endif
#include "wx/wx.h" #include "wx/wx.h"
#include "wx/app.h"
#include "wx/timer.h"
#include "wx/motif/toolbar.h" #include "wx/motif/toolbar.h"
#include <Xm/Xm.h> #include <Xm/Xm.h>
#include <Xm/PushBG.h> #include <Xm/PushBG.h>
#include <Xm/PushB.h> #include <Xm/PushB.h>
#include <Xm/Label.h>
#include <Xm/ToggleB.h> #include <Xm/ToggleB.h>
#include <Xm/ToggleBG.h> #include <Xm/ToggleBG.h>
#include <Xm/Form.h> #include <Xm/Form.h>
@ -32,6 +35,30 @@ BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase)
END_EVENT_TABLE() END_EVENT_TABLE()
#endif #endif
static void wxToolButtonCallback (Widget w, XtPointer clientData,
XtPointer ptr);
static void wxToolButtonPopupCallback (Widget w, XtPointer client_data,
XEvent *event, Boolean *continue_to_dispatch);
wxBitmap wxCreateMaskedBitmap(wxBitmap& bitmap, wxColour& colour);
class wxToolBarTimer: public wxTimer
{
public:
wxToolBarTimer() { }
virtual void Notify();
static Widget help_popup;
static Widget buttonWidget;
static wxString helpString;
};
static wxToolBarTimer* wxTheToolBarTimer = (wxToolBarTimer*) NULL;
Widget wxToolBarTimer::help_popup = (Widget) 0;
Widget wxToolBarTimer::buttonWidget = (Widget) 0;
wxString wxToolBarTimer::helpString = "";
wxToolBar::wxToolBar(): wxToolBar::wxToolBar():
m_widgets(wxKEY_INTEGER) m_widgets(wxKEY_INTEGER)
{ {
@ -39,7 +66,6 @@ wxToolBar::wxToolBar():
m_maxHeight = -1; m_maxHeight = -1;
m_defaultWidth = 24; m_defaultWidth = 24;
m_defaultHeight = 22; m_defaultHeight = 22;
// TODO
} }
bool wxToolBar::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, bool wxToolBar::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
@ -66,6 +92,10 @@ bool wxToolBar::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, cons
XmNtraversalOn, False, XmNtraversalOn, False,
XmNhorizontalSpacing, 0, XmNhorizontalSpacing, 0,
XmNverticalSpacing, 0, XmNverticalSpacing, 0,
XmNleftOffset, 0,
XmNrightOffset, 0,
XmNmarginWidth, 0,
XmNmarginHeight, 0,
NULL); NULL);
m_mainWidget = (WXWidget) toolbar; m_mainWidget = (WXWidget) toolbar;
@ -81,7 +111,10 @@ bool wxToolBar::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, cons
wxToolBar::~wxToolBar() wxToolBar::~wxToolBar()
{ {
// TODO delete wxTheToolBarTimer;
wxTheToolBarTimer = NULL;
ClearTools();
DestroyPixmaps();
} }
bool wxToolBar::CreateTools() bool wxToolBar::CreateTools()
@ -89,13 +122,21 @@ bool wxToolBar::CreateTools()
if (m_tools.Number() == 0) if (m_tools.Number() == 0)
return FALSE; return FALSE;
// Separator spacing
const int separatorSize = GetToolSeparation(); // 8;
int currentSpacing = 0;
m_widgets.Clear(); m_widgets.Clear();
Widget prevButton = (Widget) 0; Widget prevButton = (Widget) 0;
wxNode* node = m_tools.First(); wxNode* node = m_tools.First();
while (node) while (node)
{ {
wxToolBarTool *tool = (wxToolBarTool *)node->Data(); wxToolBarTool *tool = (wxToolBarTool *)node->Data();
if ((tool->m_toolStyle != wxTOOL_STYLE_SEPARATOR) && tool->m_bitmap1.Ok())
if (tool->m_toolStyle == wxTOOL_STYLE_SEPARATOR)
currentSpacing = separatorSize;
else if (tool->m_bitmap1.Ok())
{ {
Widget button = (Widget) 0; Widget button = (Widget) 0;
@ -105,12 +146,14 @@ bool wxToolBar::CreateTools()
xmToggleButtonWidgetClass, (Widget) m_mainWidget, xmToggleButtonWidgetClass, (Widget) m_mainWidget,
XmNleftAttachment, (prevButton == (Widget) 0) ? XmATTACH_FORM : XmATTACH_WIDGET, XmNleftAttachment, (prevButton == (Widget) 0) ? XmATTACH_FORM : XmATTACH_WIDGET,
XmNleftWidget, (prevButton == (Widget) 0) ? NULL : prevButton, XmNleftWidget, (prevButton == (Widget) 0) ? NULL : prevButton,
XmNleftOffset, 0, XmNleftOffset, currentSpacing,
XmNtopAttachment, XmATTACH_FORM, XmNtopAttachment, XmATTACH_FORM,
// XmNpushButtonEnabled, True, // XmNpushButtonEnabled, True,
XmNmultiClick, XmMULTICLICK_KEEP, XmNmultiClick, XmMULTICLICK_KEEP,
XmNlabelType, XmPIXMAP, XmNlabelType, XmPIXMAP,
NULL); NULL);
XtAddCallback ((Widget) button, XmNvalueChangedCallback, (XtCallbackProc) wxToolButtonCallback,
(XtPointer) this);
} }
else else
{ {
@ -118,23 +161,25 @@ bool wxToolBar::CreateTools()
xmPushButtonWidgetClass, (Widget) m_mainWidget, xmPushButtonWidgetClass, (Widget) m_mainWidget,
XmNleftAttachment, (prevButton == (Widget) 0) ? XmATTACH_FORM : XmATTACH_WIDGET, XmNleftAttachment, (prevButton == (Widget) 0) ? XmATTACH_FORM : XmATTACH_WIDGET,
XmNleftWidget, (prevButton == (Widget) 0) ? NULL : prevButton, XmNleftWidget, (prevButton == (Widget) 0) ? NULL : prevButton,
XmNleftOffset, 0, XmNleftOffset, currentSpacing,
XmNtopAttachment, XmATTACH_FORM, XmNtopAttachment, XmATTACH_FORM,
XmNpushButtonEnabled, True, XmNpushButtonEnabled, True,
XmNmultiClick, XmMULTICLICK_KEEP, XmNmultiClick, XmMULTICLICK_KEEP,
XmNlabelType, XmPIXMAP, XmNlabelType, XmPIXMAP,
NULL); NULL);
} XtAddCallback (button,
XmNactivateCallback, (XtCallbackProc) wxToolButtonCallback,
(XtPointer) this);
}
// For each button, if there is a mask, we must create // For each button, if there is a mask, we must create
// a new wxBitmap that has the correct background colour // a new wxBitmap that has the correct background colour
// for the button. Otherwise the background will just be // for the button. Otherwise the background will just be
// e.g. black if a transparent XPM has been loaded. // e.g. black if a transparent XPM has been loaded.
wxBitmap originalBitmap = tool->m_bitmap1;
if (tool->m_bitmap1.GetMask()) if (tool->m_bitmap1.GetMask())
{ {
wxBitmap newBitmap(tool->m_bitmap1.GetWidth(),
tool->m_bitmap1.GetHeight(),
tool->m_bitmap1.GetDepth());
int backgroundPixel; int backgroundPixel;
XtVaGetValues(button, XmNbackground, &backgroundPixel, XtVaGetValues(button, XmNbackground, &backgroundPixel,
NULL); NULL);
@ -143,50 +188,48 @@ bool wxToolBar::CreateTools()
wxColour col; wxColour col;
col.SetPixel(backgroundPixel); col.SetPixel(backgroundPixel);
wxMemoryDC destDC; wxBitmap newBitmap = wxCreateMaskedBitmap(tool->m_bitmap1, col);
wxMemoryDC srcDC;
srcDC.SelectObject(tool->m_bitmap1);
destDC.SelectObject(newBitmap);
wxBrush brush(col, wxSOLID);
destDC.SetOptimization(FALSE);
destDC.SetBackground(brush);
destDC.Clear();
destDC.Blit(0, 0, tool->m_bitmap1.GetWidth(), tool->m_bitmap1.GetHeight(), & srcDC, 0, 0, wxCOPY, TRUE);
tool->m_bitmap1 = newBitmap; tool->m_bitmap1 = newBitmap;
} }
// Create a selected/toggled bitmap. If there isn't a m_bitmap2,
// we need to create it (with a darker, selected background)
int backgroundPixel;
if (tool->m_isToggle)
XtVaGetValues(button, XmNselectColor, &backgroundPixel,
NULL);
else
XtVaGetValues(button, XmNarmColor, &backgroundPixel,
NULL);
wxColour col;
col.SetPixel(backgroundPixel);
if (tool->m_bitmap2.Ok() && tool->m_bitmap2.GetMask()) if (tool->m_bitmap2.Ok() && tool->m_bitmap2.GetMask())
{ {
wxBitmap newBitmap(tool->m_bitmap2.GetWidth(), // Use what's there
tool->m_bitmap2.GetHeight(), wxBitmap newBitmap = wxCreateMaskedBitmap(tool->m_bitmap2, col);
tool->m_bitmap2.GetDepth());
int backgroundPixel;
XtVaGetValues(button, XmNbackground, &backgroundPixel,
NULL);
wxColour col;
col.SetPixel(backgroundPixel);
wxMemoryDC destDC;
wxMemoryDC srcDC;
srcDC.SelectObject(tool->m_bitmap2);
destDC.SelectObject(newBitmap);
wxBrush brush(col, wxSOLID);
destDC.SetOptimization(FALSE);
destDC.SetBackground(brush);
destDC.Clear();
destDC.Blit(0, 0, tool->m_bitmap2.GetWidth(), tool->m_bitmap2.GetHeight(), & srcDC, 0, 0, wxCOPY, TRUE);
tool->m_bitmap2 = newBitmap; tool->m_bitmap2 = newBitmap;
} }
else
{
// Use unselected bitmap
if (originalBitmap.GetMask())
{
wxBitmap newBitmap = wxCreateMaskedBitmap(originalBitmap, col);
tool->m_bitmap2 = newBitmap;
}
else
tool->m_bitmap2 = tool->m_bitmap1;
}
Pixmap pixmap = (Pixmap) tool->m_bitmap1.GetPixmap(); Pixmap pixmap = (Pixmap) tool->m_bitmap1.GetPixmap();
Pixmap insensPixmap = (Pixmap) tool->m_bitmap1.GetInsensPixmap(); Pixmap insensPixmap = (Pixmap) tool->m_bitmap1.GetInsensPixmap();
if (tool->m_isToggle) if (tool->m_isToggle)
{ {
// Toggle button
Pixmap pixmap2 = (Pixmap) 0; Pixmap pixmap2 = (Pixmap) 0;
Pixmap insensPixmap2 = (Pixmap) 0; Pixmap insensPixmap2 = (Pixmap) 0;
@ -200,34 +243,53 @@ bool wxToolBar::CreateTools()
else else
{ {
pixmap2 = (Pixmap) tool->m_bitmap1.GetArmPixmap(button); pixmap2 = (Pixmap) tool->m_bitmap1.GetArmPixmap(button);
// This has to be both toggled and insensitive, but insensPixmap2 = XCreateInsensitivePixmap((Display*) wxGetDisplay(), pixmap2);
// wxBitmap doesn't yet have a member to store & destroy m_pixmaps.Append((wxObject*) insensPixmap2); // Store for later deletion
// it, so make it the same as pixmap2. Actually it's not
// used!
insensPixmap2 = pixmap2;
} }
XtVaSetValues (button, XtVaSetValues (button,
XmNlabelPixmap, pixmap, XmNindicatorOn, False,
XmNselectPixmap, pixmap, XmNshadowThickness, 2,
XmNlabelInsensitivePixmap, insensPixmap, // XmNborderWidth, 0,
XmNselectInsensitivePixmap, insensPixmap, // XmNspacing, 0,
XmNarmPixmap, pixmap2, XmNmarginWidth, 0,
XmNlabelType, XmPIXMAP, XmNmarginHeight, 0,
NULL); XmNfillOnSelect, True,
XmNlabelPixmap, pixmap,
} XmNselectPixmap, pixmap2,
XmNlabelInsensitivePixmap, insensPixmap,
XmNselectInsensitivePixmap, insensPixmap2,
XmNlabelType, XmPIXMAP,
NULL);
}
else else
{ {
Pixmap pixmap2 = (Pixmap) 0;
// If there's a bitmap for the armed state, use it,
// otherwise generate one.
if (tool->m_bitmap2.Ok())
{
pixmap2 = (Pixmap) tool->m_bitmap2.GetPixmap();
}
else
{
pixmap2 = (Pixmap) tool->m_bitmap1.GetArmPixmap(button);
}
// Normal button
XtVaSetValues(button, XtVaSetValues(button,
XmNlabelPixmap, pixmap, XmNlabelPixmap, pixmap,
XmNlabelInsensitivePixmap, insensPixmap, XmNlabelInsensitivePixmap, insensPixmap,
NULL); XmNarmPixmap, pixmap2,
NULL);
} }
XtAddEventHandler (button, EnterWindowMask | LeaveWindowMask,
False, wxToolButtonPopupCallback, (XtPointer) this);
m_widgets.Append(tool->m_index, (wxObject*) button); m_widgets.Append(tool->m_index, (wxObject*) button);
prevButton = button; prevButton = button;
currentSpacing = 0;
} }
node = node->Next(); node = node->Next();
} }
@ -261,7 +323,12 @@ void wxToolBar::EnableTool(int toolIndex, bool enable)
{ {
wxToolBarTool *tool = (wxToolBarTool *)node->Data(); wxToolBarTool *tool = (wxToolBarTool *)node->Data();
tool->m_enabled = enable; tool->m_enabled = enable;
// TODO enable button
WXWidget widget = FindWidgetForIndex(tool->m_index);
if (widget == (WXWidget) 0)
return;
XtSetSensitive((Widget) widget, (Boolean) enable);
} }
} }
@ -274,7 +341,12 @@ void wxToolBar::ToggleTool(int toolIndex, bool toggle)
if (tool->m_isToggle) if (tool->m_isToggle)
{ {
tool->m_toggleState = toggle; tool->m_toggleState = toggle;
// TODO: set toggle state
WXWidget widget = FindWidgetForIndex(tool->m_index);
if (widget == (WXWidget) 0)
return;
XmToggleButtonSetState((Widget) widget, (Boolean) toggle, False);
} }
} }
} }
@ -289,10 +361,23 @@ void wxToolBar::ClearTools()
node = node->Next(); node = node->Next();
} }
m_widgets.Clear(); m_widgets.Clear();
DestroyPixmaps();
wxToolBarBase::ClearTools(); wxToolBarBase::ClearTools();
} }
void wxToolBar::DestroyPixmaps()
{
wxNode* node = m_pixmaps.First();
while (node)
{
Pixmap pixmap = (Pixmap) node->Data();
XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) GetXDisplay()), pixmap);
node = node->Next();
}
m_pixmaps.Clear();
}
// If pushedBitmap is NULL, a reversed version of bitmap is // If pushedBitmap is NULL, a reversed version of bitmap is
// created and used as the pushed/toggled image. // created and used as the pushed/toggled image.
// If toggle is TRUE, the button toggles between the two states. // If toggle is TRUE, the button toggles between the two states.
@ -319,3 +404,180 @@ wxToolBarTool *wxToolBar::AddTool(int index, const wxBitmap& bitmap, const wxBit
return tool; return tool;
} }
int wxToolBar::FindIndexForWidget(WXWidget w)
{
wxNode* node = m_widgets.First();
while (node)
{
WXWidget widget = (WXWidget) node->Data();
if (widget == w)
return (int) node->key.integer;
node = node->Next();
}
return -1;
}
WXWidget wxToolBar::FindWidgetForIndex(int index)
{
wxNode* node = m_widgets.Find((long) index);
if (!node)
return (WXWidget) 0;
else
return (WXWidget) node->Data();
}
void wxToolButtonCallback (Widget w, XtPointer clientData,
XtPointer ptr)
{
wxToolBar *toolBar = (wxToolBar *) clientData;
int index = toolBar->FindIndexForWidget((WXWidget) w);
if (index != -1)
{
wxNode *node = toolBar->GetTools().Find((long)index);
if (!node)
return;
wxToolBarTool *tool = (wxToolBarTool *)node->Data();
if (tool->m_isToggle)
tool->m_toggleState = toolBar->GetToolState(index);
(void) toolBar->OnLeftClick(index, tool->m_toggleState);
}
}
// Creates a bitmap with transparent areas drawn in
// the given colour.
wxBitmap wxCreateMaskedBitmap(wxBitmap& bitmap, wxColour& colour)
{
wxBitmap newBitmap(bitmap.GetWidth(),
bitmap.GetHeight(),
bitmap.GetDepth());
wxMemoryDC destDC;
wxMemoryDC srcDC;
srcDC.SelectObject(bitmap);
destDC.SelectObject(newBitmap);
wxBrush brush(colour, wxSOLID);
destDC.SetOptimization(FALSE);
destDC.SetBackground(brush);
destDC.Clear();
destDC.Blit(0, 0, bitmap.GetWidth(), bitmap.GetHeight(), & srcDC, 0, 0, wxCOPY, TRUE);
return newBitmap;
}
static void wxToolButtonPopupCallback (Widget w, XtPointer client_data,
XEvent *event, Boolean *continue_to_dispatch)
{
// TODO: retrieve delay before popping up tooltip from wxSystemSettings.
int delayMilli = 800;
wxToolBar* toolBar = (wxToolBar*) client_data;
int index = toolBar->FindIndexForWidget((WXWidget) w);
if (index != -1)
{
wxNode *node = toolBar->GetTools().Find((long)index);
if (!node)
return;
wxToolBarTool *tool = (wxToolBarTool *)node->Data();
wxString str(toolBar->GetToolShortHelp(index));
if (str.IsNull() || str == "")
return;
if (!wxTheToolBarTimer)
wxTheToolBarTimer = new wxToolBarTimer;
wxToolBarTimer::buttonWidget = w;
wxToolBarTimer::helpString = str;
/************************************************************/
/* Popup help label */
/************************************************************/
if (event->type == EnterNotify)
{
if (wxToolBarTimer::help_popup != (Widget) 0)
{
XtDestroyWidget (wxToolBarTimer::help_popup);
XtPopdown (wxToolBarTimer::help_popup);
}
wxToolBarTimer::help_popup = (Widget) 0;
// One shot
wxTheToolBarTimer->Start(delayMilli, TRUE);
}
/************************************************************/
/* Popdown help label */
/************************************************************/
else if (event->type == LeaveNotify)
{
if (wxTheToolBarTimer)
wxTheToolBarTimer->Stop();
if (wxToolBarTimer::help_popup != (Widget) 0)
{
XtDestroyWidget (wxToolBarTimer::help_popup);
XtPopdown (wxToolBarTimer::help_popup);
}
wxToolBarTimer::help_popup = (Widget) 0;
}
}
}
void wxToolBarTimer::Notify()
{
Position x, y;
/************************************************************/
/* Create shell without window decorations */
/************************************************************/
help_popup = XtVaCreatePopupShell ("shell",
overrideShellWidgetClass, (Widget) wxTheApp->GetTopLevelWidget(),
NULL);
/************************************************************/
/* Get absolute position on display of toolbar button */
/************************************************************/
XtTranslateCoords (buttonWidget,
(Position) 0,
(Position) 0,
&x, &y);
// Move the tooltip more or less above the button
int yOffset = 20; // TODO: What should be really?
y -= yOffset;
if (y < yOffset) y = 0;
/************************************************************/
/* Set the position of the help popup */
/************************************************************/
XtVaSetValues (help_popup,
XmNx, (Position) x,
XmNy, (Position) y,
NULL);
/************************************************************/
/* Create help label */
/************************************************************/
XmString text = XmStringCreateSimple ((char*) (const char*) helpString);
XtVaCreateManagedWidget ("help_label",
xmLabelWidgetClass, help_popup,
XmNlabelString, text,
XtVaTypedArg,
XmNforeground, XtRString, "black",
strlen("black")+1,
XtVaTypedArg,
XmNbackground, XtRString, "LightGoldenrod",
strlen("LightGoldenrod")+1,
NULL);
XmStringFree (text);
/************************************************************/
/* Popup help label */
/************************************************************/
XtPopup (help_popup, XtGrabNone);
}