Sliding Dialogs (Sheets) for MacOS X Leopard Topic is solved
-
- Earned a small fee
- Posts: 11
- Joined: Sat Jan 26, 2008 12:52 am
- Location: Palo Alto, CA
- Contact:
Sliding Dialogs (Sheets) for MacOS X Leopard
Is there a way to get a sliding dialog like this (on MacOS):
(This one from msw Safari, but you know what I'm saying.) Leopard is crammed full of such dialogs.
(This one from msw Safari, but you know what I'm saying.) Leopard is crammed full of such dialogs.
Last edited by joric on Wed May 07, 2008 7:31 pm, edited 4 times in total.
-
- I live to help wx-kind
- Posts: 194
- Joined: Mon Aug 30, 2004 1:26 pm
- Location: PA, USA
- Contact:
-
- I live to help wx-kind
- Posts: 194
- Joined: Mon Aug 30, 2004 1:26 pm
- Location: PA, USA
- Contact:
Right, so I guess it's not in wx itself.
Apple's Dev Docs should help a bit here, but I think something like this should work (but untested...)
It's important to override the Show() method (and NOT call inherited) because we're showing the sheet in a different way.[/code]
Apple's Dev Docs should help a bit here, but I think something like this should work (but untested...)
Code: Select all
bool MySheetWindow::Show(bool visible)
{
if (visible)
{
::ShowSheetWindow( MacGetWindowRef(), GetParent()->MacGetWindowRef() );
Refresh();
}
else
::HideSheetWindow( MacGetWindowRef() );
return true;
}
//Then just construct a MySheetWindow in the normal way, making sure to specify, as the parent parameter, the window you want to be "under" the sheet.
//(OR, if the parent doesn't work, make a freshly named instance variable...)
-
- I live to help wx-kind
- Posts: 194
- Joined: Mon Aug 30, 2004 1:26 pm
- Location: PA, USA
- Contact:
-
- Earned a small fee
- Posts: 11
- Joined: Sat Jan 26, 2008 12:52 am
- Location: Palo Alto, CA
- Contact:
I've searched in the forum about ShowSheetWindow and got this topic: http://forums.wxwidgets.org/viewtopic.php?t=19076
As there were no implementation details i've hacked a source.
Then I've recompiled entire wxWidgets with make && sudo make install (one single file, so it's pretty fast) and it works like a charm!
To remove dialog captions you have to replace wxDEFAULT_DIALOG_STYLE to wxBORDER_NONE (an empty style gives ugly thin black border).
I didn't make a sleeker implementation, but it worth to be implemented as, say, additional dialog style in any next release of wxMac.
As there were no implementation details i've hacked a source.
Code: Select all
//wxWidgets-2.8.7/src/mac/carbon/dialog.cpp
...
bool wxDialog::Show(bool show)
{
/*
if ( !wxDialogBase::Show(show) )
// nothing to do
return false;
*/
wxFrame * dialog = (wxFrame*)this;
wxFrame * frame = (wxFrame*)GetParent();
if (show)
{
SetWindowClass (
(WindowRef) dialog->MacGetWindowRef(),
kSheetWindowClass );
ShowSheetWindow (
(WindowRef) dialog->MacGetWindowRef(),
(WindowRef) frame->MacGetWindowRef());
}
else
{
HideSheetWindow(
(WindowRef) dialog->MacGetWindowRef());
}
...
To remove dialog captions you have to replace wxDEFAULT_DIALOG_STYLE to wxBORDER_NONE (an empty style gives ugly thin black border).
I didn't make a sleeker implementation, but it worth to be implemented as, say, additional dialog style in any next release of wxMac.
-
- Earned a small fee
- Posts: 11
- Joined: Sat Jan 26, 2008 12:52 am
- Location: Palo Alto, CA
- Contact:
I've made a patch.
Code: Select all
Name: wxWidgets 2.8.7 patch to enable MacOS sliding dialogs (sheets)
Version: 0.0.1
Usage: add wxBORDER_NONE style to dialog (does not affect anything else)
Maintainers: Joric (http://joreg.livejournal.com)
===================================================================
--- wxWidgets-2.8.7/src/mac/dialog.cpp 2007-11-21 17:43:24.000000000 +0500
+++ wxWidgets-2.8.7/src/mac/dialog.cpp 2008-05-06 22:16:04.000000000 +0600
@@ -49,6 +49,9 @@
// ...but not these styles
style &= ~(wxYES | wxOK | wxNO); // | wxCANCEL
+
+ if (style & wxBORDER_NONE)
+ style = wxBORDER_NONE;
if ( !wxTopLevelWindow::Create( parent, id, title, pos, size, style, name ) )
return false;
@@ -106,9 +109,20 @@
bool wxDialog::Show(bool show)
{
- if ( !wxDialogBase::Show(show) )
- // nothing to do
- return false;
+ if ( ( GetWindowStyleFlag() & wxBORDER_NONE ) && GetParent() )
+ {
+ if (show)
+ {
+ SetWindowClass ( (WindowRef) MacGetWindowRef(), kSheetWindowClass );
+
+ ShowSheetWindow ( (WindowRef) MacGetWindowRef(),
+ (WindowRef) ( ( wxFrame* ) GetParent() )->MacGetWindowRef() );
+ }
+ else
+ HideSheetWindow( (WindowRef) MacGetWindowRef() );
+ }
+ else
+ {
+ if ( !wxDialogBase::Show(show) )
+ return false;
+ }
if ( show )
// usually will result in TransferDataToWindow() being called
Last edited by joric on Wed May 07, 2008 1:02 am, edited 1 time in total.
-
- Earned a small fee
- Posts: 11
- Joined: Sat Jan 26, 2008 12:52 am
- Location: Palo Alto, CA
- Contact:
Unfortunately there is a significant difference between these sheets and native leopard sheets. They are not semi-transparent and have bigger shadow (i've tried several styles). I don't know why, does anybody know?
P.S. It maybe because i've linked in 10.4u compatibility mode, haven't checked with 10.5 SDK yet (it tooks awful amount of time to recompile the whole lib). But I think it's not the real case... Btw it looks much more native on Tiger.
P.P.S. I've tried to use style = 0, it gives the proper (small) shadow, but no transparency and the black border returned. Do you know a proper style for it?
P.S. It maybe because i've linked in 10.4u compatibility mode, haven't checked with 10.5 SDK yet (it tooks awful amount of time to recompile the whole lib). But I think it's not the real case... Btw it looks much more native on Tiger.
P.P.S. I've tried to use style = 0, it gives the proper (small) shadow, but no transparency and the black border returned. Do you know a proper style for it?
-
- Earned a small fee
- Posts: 11
- Joined: Sat Jan 26, 2008 12:52 am
- Location: Palo Alto, CA
- Contact:
One more patch (for alerts / message dialogs). Looks like transparent, compiled on 10.4u.
A bit agressive patch =) Turns all modal message boxes to "sheets".
Code: Select all
Name: wxWidgets 2.8.7 patch to enable "Sheet" style for MacOS message dialogs
Version: 0.0.1
Usage: affects all message dialogs, no flags needed
Maintainers: Joric (http://joreg.livejournal.com)
===================================================================
--- wxWidgets-2.8.7/src/mac/msgdlg.cpp 2007-11-21 18:43:25.000000000 +0500
+++ wxWidgets-2.8.7/src/mac/msgdlg.cpp 2008-05-07 06:39:28.000000000 +0600
@@ -34,6 +34,42 @@
SetMessageDialogStyle(style);
}
+pascal OSStatus mySheetHandler( EventHandlerCallRef inRef,
+ EventRef inEvent,
+ void* userData)
+{
+
+ ControlRef control;
+ WindowRef sheet;
+ WindowRef parent;
+ UInt32 cmd;
+ GetEventParameter(inEvent, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &control);
+ GetControlCommandID(control, &cmd);
+ sheet = GetControlOwner(control);
+ GetSheetWindowParent(sheet, &parent);
+ HideSheetWindow(sheet);
+ DisposeWindow(sheet);
+ QuitAppModalLoopForWindow(parent);
+ short result = -1;
+ switch(cmd)
+ {
+ case kHICommandOK:
+ result = 1;
+ break;
+
+ case kHICommandCancel:
+ result = 2;
+ break;
+
+ case kHICommandOther:
+ result = 3;
+ break;
+ }
+ *(short*)userData = result;
+ return noErr;
+}
+
+
int wxMessageDialog::ShowModal()
{
int resultbutton = wxID_CANCEL;
@@ -177,9 +213,13 @@
param.position = kWindowDefaultPosition;
if ( !skipDialog )
{
- DialogRef alertRef;
- CreateStandardAlert( alertType, cfTitle, cfText, ¶m, &alertRef );
- RunStandardAlert( alertRef, NULL, &result );
+ DialogRef sheet = NULL;
+ static EventTypeSpec controlEvent = { kEventClassControl, kEventControlHit };
+ WindowRef parent = (WindowRef)((wxTopLevelWindow*) m_parent)->MacGetWindowRef();
+ CreateStandardSheet(alertType, cfTitle, cfText, ¶m, GetWindowEventTarget(parent), &sheet);
+ InstallWindowEventHandler(GetDialogWindow(sheet), NewEventHandlerUPP(mySheetHandler), 1, &controlEvent, &result, NULL);
+ ShowSheetWindow(GetDialogWindow(sheet), parent);
+ RunAppModalLoopForWindow(parent);
}
else
{
-
- I live to help wx-kind
- Posts: 194
- Joined: Mon Aug 30, 2004 1:26 pm
- Location: PA, USA
- Contact:
-
- Earned a small fee
- Posts: 11
- Joined: Sat Jan 26, 2008 12:52 am
- Location: Palo Alto, CA
- Contact:
Subclassed version, no need to patch now.
If you meant this kind of subclassing (i.e. copypasting), it may for sure follow compatibility issues with future versions - dunno about wxFrame code tho, maybe it's better structured. BTW it does not allow to use DECLARE_DYNAMIC_CLASS or IMPLEMENT_DYNAMIC_CLASS, don't know why ("no appropriate default constructor available" even with wxMyMessageDialog(){}). But since XRC does not support message boxes it probably doesn't matter.
If you meant this kind of subclassing (i.e. copypasting), it may for sure follow compatibility issues with future versions - dunno about wxFrame code tho, maybe it's better structured. BTW it does not allow to use DECLARE_DYNAMIC_CLASS or IMPLEMENT_DYNAMIC_CLASS, don't know why ("no appropriate default constructor available" even with wxMyMessageDialog(){}). But since XRC does not support message boxes it probably doesn't matter.
Code: Select all
// wxMyMessageDialog.h (for 2.8.7) enables "sheets" on MacOS
// compiled and checked on MacOS 10.4.4 and MacOS 10.5.1, both with 10.4u SDK
#if defined(__WXMAC__) && !defined(__WXMAC_CLASSIC__) && !defined(TARGET_API_MAC_OSX)
#include "wx/wxprec.h"
#include "wx/msgdlg.h"
#ifndef WX_PRECOMP
#include "wx/intl.h"
#include "wx/app.h"
#endif
#include "wx/mac/uma.h"
pascal OSStatus mySheetHandler(EventHandlerCallRef inRef, EventRef inEvent, void* userData)
{
ControlRef control;
WindowRef sheet;
WindowRef parent;
UInt32 cmd;
GetEventParameter(inEvent, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &control);
GetControlCommandID(control, &cmd);
sheet = GetControlOwner(control);
GetSheetWindowParent(sheet, &parent);
HideSheetWindow(sheet);
DisposeWindow(sheet);
QuitAppModalLoopForWindow(parent);
short result = -1;
switch(cmd)
{
case kHICommandOK:
result = 1;
break;
case kHICommandCancel:
result = 2;
break;
case kHICommandOther:
result = 3;
break;
}
*(short*)userData = result;
return noErr;
}
class wxMyMessageDialog : public wxMessageDialog
{
public:
wxMyMessageDialog(wxWindow *parent, const wxString& message, const wxString& caption = wxMessageBoxCaptionStr,
long style = wxOK|wxCENTRE, const wxPoint& pos = wxDefaultPosition)
: wxMessageDialog(parent, message, caption, style, pos){};
int ShowModal()
{
int resultbutton = wxID_CANCEL;
const long style = GetMessageDialogStyle();
wxASSERT_MSG( (style & 0x3F) != wxYES, wxT("this style is not supported on Mac") );
AlertType alertType = kAlertPlainAlert;
if (style & wxICON_EXCLAMATION)
alertType = kAlertCautionAlert;
else if (style & wxICON_HAND)
alertType = kAlertStopAlert;
else if (style & wxICON_INFORMATION)
alertType = kAlertNoteAlert;
else if (style & wxICON_QUESTION)
alertType = kAlertNoteAlert;
short result;
AlertStdCFStringAlertParamRec param;
wxMacCFStringHolder cfNoString( _("No"), m_font.GetEncoding() );
wxMacCFStringHolder cfYesString( _("Yes"), m_font.GetEncoding() );
wxMacCFStringHolder cfTitle( m_caption, m_font.GetEncoding() );
wxMacCFStringHolder cfText( m_message, m_font.GetEncoding() );
param.movable = true;
param.flags = 0;
param.version = kStdCFStringAlertVersionOne;
bool skipDialog = false;
if (style & wxYES_NO)
{
if (style & wxCANCEL)
{
param.defaultText = cfYesString;
param.cancelText = (CFStringRef) kAlertDefaultCancelText;
param.otherText = cfNoString;
param.helpButton = false;
param.defaultButton = style & wxNO_DEFAULT ? kAlertStdAlertOtherButton : kAlertStdAlertOKButton;
param.cancelButton = kAlertStdAlertCancelButton;
}
else
{
param.defaultText = cfYesString;
param.cancelText = NULL;
param.otherText = cfNoString;
param.helpButton = false;
param.defaultButton = style & wxNO_DEFAULT ? kAlertStdAlertOtherButton : kAlertStdAlertOKButton;
param.cancelButton = 0;
}
}
// the MSW implementation even shows an OK button if it is not specified, we'll do the same
else
{
if (style & wxCANCEL)
{
// that's a cancel missing
param.defaultText = (CFStringRef) kAlertDefaultOKText;
param.cancelText = (CFStringRef) kAlertDefaultCancelText;
param.otherText = NULL;
param.helpButton = false;
param.defaultButton = kAlertStdAlertOKButton;
param.cancelButton = 0;
}
else
{
param.defaultText = (CFStringRef) kAlertDefaultOKText;
param.cancelText = NULL;
param.otherText = NULL;
param.helpButton = false;
param.defaultButton = kAlertStdAlertOKButton;
param.cancelButton = 0;
}
}
param.position = kWindowDefaultPosition;
if ( !skipDialog )
{
if (m_parent == NULL)
{
// if no parent, use the old version
DialogRef alertRef;
CreateStandardAlert( alertType, cfTitle, cfText, ¶m, &alertRef );
RunStandardAlert( alertRef, NULL, &result );
}
else
{
// else use the new one
DialogRef sheet = NULL;
static EventTypeSpec controlEvent = { kEventClassControl, kEventControlHit };
WindowRef parent = (WindowRef)((wxTopLevelWindow*) m_parent)->MacGetWindowRef();
CreateStandardSheet(alertType, cfTitle, cfText, ¶m, GetWindowEventTarget(parent), &sheet);
InstallWindowEventHandler(GetDialogWindow(sheet), NewEventHandlerUPP(mySheetHandler), 1,
&controlEvent, &result, NULL);
ShowSheetWindow(GetDialogWindow(sheet), parent);
RunAppModalLoopForWindow(parent);
}
}
else
{
return wxID_CANCEL;
}
if (style & wxOK)
{
switch ( result )
{
case 1:
resultbutton = wxID_OK;
break;
case 2:
// TODO: add Cancel button
// if (style & wxCANCEL)
// resultbutton = wxID_CANCEL;
break;
case 3:
default:
break;
}
}
else if (style & wxYES_NO)
{
switch ( result )
{
case 1:
resultbutton = wxID_YES;
break;
case 2:
if (!(style & wxCANCEL))
resultbutton = wxID_CANCEL;
break;
case 3:
resultbutton = wxID_NO;
break;
default:
break;
}
}
return resultbutton;
}
};
#else
class wxMyMessageDialog : public wxMessageDialog
{
public:
wxMyMessageDialog(wxWindow *parent, const wxString& message,
const wxString& caption = wxMessageBoxCaptionStr, long style = wxOK|wxCENTRE,
const wxPoint& pos = wxDefaultPosition)
: wxMessageDialog(parent, message, caption, style, pos) {};
};
#endif