CtrlCore, CtrlLib: Cocoa dock menu support

git-svn-id: svn://ultimatepp.org/upp/trunk@12717 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2019-01-25 18:40:45 +00:00
parent 615ee3d8ca
commit e8f9edd7ac
7 changed files with 83 additions and 8 deletions

View file

@ -4,6 +4,22 @@
#ifdef PLATFORM_COCOA
@interface AppDelegate : NSObject<NSApplicationDelegate>
{
}
@end
namespace Upp {
NSMenu *Cocoa_DockMenu();
};
@implementation AppDelegate
- (NSMenu *)applicationDockMenu:(NSApplication *)sender
{
return Upp::Cocoa_DockMenu();
}
@end
namespace Upp {
int Ctrl::WndCaretTime;
@ -48,6 +64,8 @@ void CocoInit(int argc, const char **argv, const char **envptr)
[appMenuItem setSubmenu:appMenu];
[NSApp setMainMenu:menubar];
[NSApp setDelegate:[[AppDelegate alloc] init]];
NSFont *sysfont = [NSFont systemFontOfSize:0];
Font::SetFace(0, ToString((CFStringRef)[sysfont familyName]), Font::TTF);

View file

@ -27,6 +27,13 @@
return active && ctrl && ctrl->IsEnabled() && dynamic_cast<Upp::TopWindow *>(~ctrl) && !ctrl->GetOwner();
}
- (NSMenu *)applicationDockMenu:(NSApplication *)sender {
NSMenu *menu = [[[NSMenu alloc] initWithTitle:@"DocTile Menu"] autorelease];
NSMenuItem *item = [[[NSMenuItem alloc] initWithTitle:@"Hello" action:@selector(hello) keyEquivalent:@"k"] autorelease];
[menu addItem:item];
return menu;
}
@end
namespace Upp {
@ -45,7 +52,7 @@ Ctrl *Ctrl::GetActiveCtrl()
for(Ctrl *p : mmtopctrl)
if(p && p->top && p->top->coco && p->top->coco->window.keyWindow)
return p;
return NULL;
return lastActive;
}
bool Ctrl::SetWndFocus()

View file

@ -11,6 +11,7 @@ private:
static bool WndCaretVisible;
static bool local_dnd_copy;
static void AnimateCaret();
static Ptr<Ctrl> lastActive;
friend void CocoInit(int argc, const char **argv, const char **envptr);

View file

@ -12,6 +12,8 @@ static bool coco_mouse_right;
static int coco_flags;
static Upp::Ptr<Upp::Ctrl> coco_capture;
Upp::Ptr<Upp::Ctrl> Upp::Ctrl::lastActive;
namespace Upp {
extern id menubar;
@ -113,6 +115,7 @@ struct MMImp {
static bool MouseDownEvent(CocoView *view, NSEvent *e, int button)
{
Upp::Ctrl::lastActive = view->ctrl;
if(Ctrl::ignoremouseup) {
Ctrl::KillRepeat();
Ctrl::ignoreclick = false;
@ -179,6 +182,7 @@ struct MMImp {
static void BecomeKey(Upp::Ctrl *ctrl)
{
LLOG("Become key " << Upp::Name(ctrl));
Upp::Ctrl::lastActive = ctrl;
ctrl->ActivateWnd();
auto tw = dynamic_cast<TopWindow *>(ctrl);
if(tw && tw->placefocus) {

View file

@ -8,14 +8,18 @@ protected:
virtual void MMClose() { WhenClose(); }
static TopWindow *GetMenuTopWindow();
static void SyncMainMenu(bool force);
void *menubar = NULL;
Event<Bar&> MainMenu;
public: // really private:
static TopWindow *GetMenuTopWindow(bool dock);
public:
virtual bool HotKey(dword key);
Event<Bar&> WhenDockMenu;
void SetMainMenu(Event<Bar&> menu);
//$ };

View file

@ -3,6 +3,8 @@ brew install gdb
sooner:
- replace block dialog has wrong layout
- dropping DropList several times can lead to focus issue
- cursor problem after local menu invocation (better, but still...)

View file

@ -25,6 +25,7 @@ namespace Upp {
struct CocoMenuBar : public Bar {
CocoMenu *cocomenu;
int lock = 0;
bool dockmenu = false;
struct Item : Bar::Item {
NSMenuItem *nsitem;
@ -85,14 +86,27 @@ struct CocoMenuBar : public Bar {
void Set(Event<Bar&> bar);
CocoMenuBar() {
void Clear() {
item.Clear();
if(cocomenu) {
[cocomenu release];
cocomenu = NULL;
}
}
void New() {
Clear();
cocomenu = [CocoMenu new];
cocomenu.autoenablesItems = NO;
cocomenu->ptr = this;
cocomenu.delegate = cocomenu;
}
CocoMenuBar() {
cocomenu = NULL;
New();
}
~CocoMenuBar() {
[cocomenu release];
Clear();
}
};
@ -189,6 +203,8 @@ bool CocoMenuBar::IsEmpty() const
- (void)menuWillOpen:(NSMenu *)menu {
CocoMenu *m = (CocoMenu *)menu;
if(m && m->ptr && m->ptr->dockmenu)
return;
if(m && m->ptr && proc) {
[m removeAllItems];
proc(*m->ptr);
@ -197,6 +213,8 @@ bool CocoMenuBar::IsEmpty() const
- (void)menuDidClose:(NSMenu *)menu {
CocoMenu *m = (CocoMenu *)menu;
if(m && m->ptr && m->ptr->dockmenu)
return;
[m removeAllItems];
}
@ -234,15 +252,17 @@ bool TopWindow::HotKey(dword key)
return Ctrl::HotKey(key);
}
TopWindow *TopWindow::GetMenuTopWindow()
TopWindow *TopWindow::GetMenuTopWindow(bool dock)
{
Ctrl *q = GetFocusCtrl();
if(!q)
q = GetActiveCtrl();
if(!q)
return NULL;
q = q->GetTopCtrl();
while(q) {
TopWindow *w = dynamic_cast<TopWindow *>(q);
if(w && w->menubar)
if(w && (dock ? (bool)w->WhenDockMenu : (bool)w->menubar))
return w;
q = q->GetOwner();
}
@ -251,7 +271,7 @@ TopWindow *TopWindow::GetMenuTopWindow()
void TopWindow::SyncMainMenu(bool force)
{
TopWindow *w = GetMenuTopWindow();
TopWindow *w = GetMenuTopWindow(false);
static TopWindow *current;
if(w != current || force) {
current = w;
@ -264,7 +284,7 @@ void TopWindow::SyncMainMenu(bool force)
void MenuBar::ExecuteHostBar(Ctrl *owner, Point p)
{
if(host_bar) {
if(host_bar && owner) {
CocoMenuBar& bar = *(CocoMenuBar *)~host_bar;
owner = owner->GetTopCtrl();
@ -289,6 +309,25 @@ void MenuBar::CreateHostBar(One<Bar>& bar)
host_bar.Create<CocoMenuBar>();
}
NSMenu *Cocoa_DockMenu() {
Upp::TopWindow *w = Upp::TopWindow::GetMenuTopWindow(true);
if(w && w->WhenDockMenu) {
static Upp::CocoMenuBar bar;
bar.dockmenu = true;
bar.Clear();
bar.cocomenu = [[[CocoMenu alloc] initWithTitle:@"DocTile Menu"] autorelease];
bar.cocomenu.autoenablesItems = NO;
bar.cocomenu->ptr = &bar;
bar.cocomenu.delegate = bar.cocomenu;
w->WhenDockMenu(bar);
CocoMenu *m = bar.cocomenu;
bar.cocomenu = NULL;
return m;
}
return nil;
}
};
#endif