Skip to content

Commit

Permalink
better widget user experience, on OSX in particular. And a few bugs c…
Browse files Browse the repository at this point in the history
…ured. (#1878)
  • Loading branch information
GillesDuvert authored Sep 12, 2024
1 parent 210068d commit fb0caa0
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 143 deletions.
10 changes: 1 addition & 9 deletions src/gdleventhandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,10 @@ int GDLEventHandler()
#endif
GraphicsDevice::HandleEvents();

const long OS_X_DELAY_NS = 20000000; // 20ms
//ONLY APPLE? or WIN? Why? (GD)
#ifdef __APPLE__
// under OS X the event loop burns to much CPU time
struct timespec delay;
delay.tv_sec=0;
delay.tv_nsec = OS_X_DELAY_NS; // 20ms
nanosleep(&delay,NULL);
#endif
#ifdef _WIN32
Sleep(10); // this just to quiet down the character input from readline. 2 was not enough. 20 was ok.
#endif

return 0;
}

79 changes: 34 additions & 45 deletions src/gdlwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,11 @@ bool GDLWidget::handlersOk=false;
wxFont GDLWidget::defaultFont=wxNullFont; //the font defined by widget_control,default_font.
wxFont GDLWidget::systemFont=wxNullFont; //the initial system font. This to behave as IDL

#ifdef __WXMAC__
#include <Carbon/Carbon.h>
extern "C" { void CPSEnableForegroundOperation( ProcessSerialNumber* psn ); }
#endif

//initialize wxWidgets system: create an instance of wxAppGDL here, not at Main (
#ifndef __WXMAC__
wxAppGDL& wxGetApp() { return *static_cast<wxAppGDL*>(wxApp::GetInstance()); }
Expand Down Expand Up @@ -1229,9 +1234,9 @@ void GDLWidget::RefreshDynamicWidget() {
}
}

void GDLWidget::SendWidgetTimerEvent(DDouble secs) {
void GDLWidget::SendWidgetTimerEvent(int millisecs) {
if (millisecs < 1) millisecs=1; //otherwise 0 hangs on OSX
WidgetIDT* id = new WidgetIDT(widgetID);
int millisecs = floor(secs * 1000.0);
if (theWxWidget) { //we nee a handle on a wxWindow object...
wxWindow* w = dynamic_cast<wxWindow*> (theWxWidget);
assert(w != NULL);
Expand Down Expand Up @@ -1259,24 +1264,14 @@ void GDLWidget::HandleUnblockedWidgetEvents()
DStructGDL* ev = NULL;
while( (ev = GDLWidget::InteractiveEventQueue.Pop()) != NULL)
{
// static int idIx = ev->Desc( )->TagIndex( "ID" ); // 0
// static int topIx = ev->Desc( )->TagIndex( "TOP" ); // 1
// static int handlerIx = ev->Desc( )->TagIndex( "HANDLER" ); // 2
// assert( idIx == 0 );
// assert( topIx == 1 );
// assert( handlerIx == 2 );

ev = CallEventHandler( ev );

if( ev != NULL)
{
int idIx = ev->Desc( )->TagIndex( "ID" );
assert( idIx == 0 );
WidgetIDT id = (*static_cast<DLongGDL*> (ev->GetTag( idIx, 0 )))[0];
Warning( "Unhandled event. ID: " + i2s( id ) );
GDLDelete( ev );
ev = NULL;
}
CallWXEventLoop(); // eneble results of above in the widgets
}
if (wxIsBusy()) wxEndBusyCursor( );
}
Expand Down Expand Up @@ -1412,22 +1407,11 @@ DLongGDL* GDLWidget::GetAllHeirs(){
for (SizeT i = 0; i < currentVectorSize ; ++i) (*result)[i] = widgetIDList[i];
return result;
}
#ifdef __WXMAC__
#include <Carbon/Carbon.h>
extern "C" { void CPSEnableForegroundOperation( ProcessSerialNumber* psn ); }
#endif

//
bool GDLWidget::InitWx() {
// this hack enables to have a GUI on Mac OSX even if the
// program was called from the command line (and isn't a bundle)
#ifdef __WXMAC__
ProcessSerialNumber psn;

GetCurrentProcess( &psn );
CPSEnableForegroundOperation( &psn );
SetFrontProcess( &psn );
#endif
try{
wxInitialize();
} catch (...) {return false;}
Expand Down Expand Up @@ -2455,19 +2439,11 @@ long style = (wxMINIMIZE_BOX | wxMAXIMIZE_BOX | wxRESIZE_BORDER | wxCAPTION | wx
}
topFrame = new gdlwxFrame(NULL, this, widgetID, titleWxString, wOffset, wxDefaultSize, style, modal);

#ifdef __wxMAC__
#ifdef __WXMAC__
//does not work.
//#include <ApplicationServices/ApplicationServices.h>
//
//ProcessSerialNumber PSN;
//GetCurrentProcess(&PSN);
//TransformProcessType(&PSN,kProcessTransformToForegroundApplication);

//the following is not really working either, except that a 'gdl' mac menubar is present an that's sufficient to get keyboard focus correctly
wxMenu* macmenu[1];
WXMenubar* macBar=new wxMenubar();
macBar->Append(OSXGetAppleMenu (), titleWxString)
topFrame->SetMenuBar(macBar);
ProcessSerialNumber psn = {0, kCurrentProcess};
ProcessApplicationTransformState state = kProcessTransformToForegroundApplication;
OSStatus osxErr = TransformProcessType(&psn, state);
#endif

#ifdef GDL_DEBUG_WIDGETS_COLORIZE
Expand All @@ -2479,22 +2455,34 @@ wxMenu* macmenu[1];
//add icon
topFrame->SetIcon(wxgdlicon);

wxSizer* tfSizer=new wxBoxSizer(wxVERTICAL);
topFrame->SetSizer(tfSizer);
if (mbarID != 0) {
#if PREFERS_MENUBAR
GDLWidgetMenuBar* mBar = new GDLWidgetMenuBar(widgetID, e);
mbarID = mBar->GetWidgetID();
mBarIDInOut = mbarID;
wxMenuBar* me = dynamic_cast<wxMenuBar*> (mBar->GetWxWidget());
#ifdef __WXMAC__
// me->Append(me->OSXGetAppleMenu(), "Apple");
// if (!osxErr) me->Append(new wxMenu("does not work\n"));
#endif
if (me) topFrame->SetMenuBar(me);
else cerr << "Warning: GDLWidgetBase::GDLWidgetBase: Non-existent menubar widget!\n";
#else

#ifdef __WXMAC__
wxPanel* p = new wxPanel(topFrame, wxID_ANY);
GDLWidgetMenuBar* mBar = new GDLWidgetMenuBar(p, widgetID, e);
wxBoxSizer* mbs=new wxBoxSizer(wxHORIZONTAL);
tfSizer->Add(p);
#else
GDLWidgetMenuBar* mBar = new GDLWidgetMenuBar(topFrame, widgetID, e);
#endif
mbarID = mBar->GetWidgetID();
mBarIDInOut = mbarID;
#endif
}
wxSizer* tfSizer=new wxBoxSizer(wxVERTICAL);
topFrame->SetSizer(tfSizer);
CreateBase(topFrame); //define widgetPanel, widgetSizer, theWxWidget and theWxContainer.
//it is the FRAME that manage all events. Here we dedicate particularly the tlb_* events:
// note that we have the choice for Size Event Handler for Frames, but need to change also is widgets.cpp
Expand Down Expand Up @@ -4841,7 +4829,7 @@ BaseGDL* GDLWidgetTable::GetDisjointSelectionValuesForStructs(DLongGDL* selectio
ix = (*selection)[l++];
t = (*selection)[l++];
}
sprintf(tagbuf, "%12d", outTag);
snprintf(tagbuf, 12, "%12d", outTag);
//convert ' ' to '_'
for (auto z = 0; z < 12; ++z) if (tagbuf[z] == 32) tagbuf[z] = 95;
std::string outTagName(const_cast<char *>(tagbuf));
Expand Down Expand Up @@ -5644,12 +5632,13 @@ GDLWidgetTree::GDLWidgetTree( WidgetIDT p, EnvT* e, BaseGDL* value_, DULong even
} //else throw GDLException("Parent tree widget is not a folder."); //IDL just forgets.
}
void GDLWidgetTree::OnRealize(){
GDLWidgetTree* root=this->GetMyRootGDLWidgetTree();
if (this==root) {
wxTreeCtrlGDL* ctrl=static_cast<wxTreeCtrlGDL*>(this->GetWxWidget());
wxTreeItemId id=ctrl->GetFirstVisibleItem ( ) ;
if (id) ctrl->SetFocusedItem(id);
}
// not useful? root node does not seem selected at creation with *DL.
// GDLWidgetTree* root=this->GetMyRootGDLWidgetTree();
// if (this==root) {
// wxTreeCtrlGDL* ctrl=static_cast<wxTreeCtrlGDL*>(this->GetWxWidget());
// wxTreeItemId id=ctrl->GetFirstVisibleItem ( ) ;
// if (id) ctrl->SetFocusedItem(id);
// }
}
DInt GDLWidgetTree::GetTreeIndex()
{
Expand Down
23 changes: 17 additions & 6 deletions src/gdlwidget.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
// on OSX. So we choose normally to undefine this
#ifndef __WXMAC__
//warning MAC should not have prefer_menubar=1 unless you solve the mac manubar problem.
#define PREFERS_MENUBAR 1
//#define PREFERS_MENUBAR 1
#endif
// For compilers that support precompilation, includes "wx/wx.h".
// HAVE_LARGEFILE_SUPPORT, SIZEOF_VOID_P, SIZEOF_SIZE_T, may be set by Python, creates unnecessary warnings
Expand Down Expand Up @@ -255,7 +255,7 @@ class WidgetEventInfo {
#ifndef __WXMAC__
// main App class
#include "wx/evtloop.h"

class wxAppGDL: public wxApp
{
wxGUIEventLoop loop;
Expand Down Expand Up @@ -793,7 +793,7 @@ class GDLWidget
bool DisableSizeEvents(gdlwxFrame* &tlbFrame,WidgetIDT &id);
static void EnableSizeEvents(gdlwxFrame* &tlbFrame,WidgetIDT &id);

void SendWidgetTimerEvent(DDouble secs);
void SendWidgetTimerEvent(int millisecs);
virtual void SetButtonWidget( bool onOff){}
void ClearEvents();
};
Expand Down Expand Up @@ -1085,7 +1085,7 @@ class wxButtonGDL: public wxButton
this->SetFont(font);
popupMenu=new wxMenu();
position=this->GetClientRect().GetBottomLeft();
Connect(id, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(wxButtonGDL::OnButton));
// Connect(id, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(wxButtonGDL::OnButton));
Connect(id, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(wxButtonGDL::OnButton));
}
wxMenu* GetPopupMenu(){return popupMenu;}
Expand All @@ -1097,6 +1097,7 @@ class wxButtonGDL: public wxButton
class wxBitmapButtonGDL: public wxBitmapButton
{
wxMenu* popupMenu;
wxPoint position;
public:
wxBitmapButtonGDL(wxWindow *parent,
wxWindowID id,
Expand All @@ -1108,7 +1109,8 @@ class wxBitmapButtonGDL: public wxBitmapButton
const wxString &name=wxButtonNameStr):
wxBitmapButton(parent,id,bitmap_,pos,size,style,validator,name){
popupMenu=new wxMenu();
Connect(id, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(wxBitmapButtonGDL::OnButton));
position=this->GetClientRect().GetBottomLeft();
// Connect(id, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(wxBitmapButtonGDL::OnButton));
Connect(id, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(wxBitmapButtonGDL::OnButton));
}
wxMenu* GetPopupMenu(){return popupMenu;}
Expand Down Expand Up @@ -1529,11 +1531,20 @@ class GDLWidgetMenuBar: public GDLWidget
std::deque<WidgetIDT> children;
~GDLWidgetMenuBar();
public:
#ifdef __WXMAC__
GDLWidgetMenuBar( wxWindow* frame, WidgetIDT p, EnvT* e):
#else
GDLWidgetMenuBar( wxFrame* frame, WidgetIDT p, EnvT* e):
#endif
GDLWidget( p, NULL) //NULL because MBar must not re-read env Values of e
{
long style=wxTB_HORIZONTAL|wxTB_DOCKABLE|wxTB_FLAT;
long style=wxHORIZONTAL|wxTB_DOCKABLE|wxTB_FLAT;
//Do not ask me why this works on mac and not other way.
#ifdef __WXMAC__
wxToolBar* t= new wxToolBar(frame, wxID_ANY);
#else
wxToolBar* t= frame->CreateToolBar(style, wxID_ANY);
#endif
theWxWidget = theWxContainer = t;
// widgetSizer=new wxBoxSizer(wxHORIZONTAL);
// t->SetSizer(widgetSizer);
Expand Down
Loading

0 comments on commit fb0caa0

Please sign in to comment.