xref: /trunk/main/vcl/aqua/source/window/salnsmenu.mm (revision 01367266)
1/**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements.  See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership.  The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License.  You may obtain a copy of the License at
10 *
11 *   http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied.  See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24// MARKER(update_precomp.py): autogen include statement, do not remove
25#include "precompiled_vcl.hxx"
26
27#include "aqua/salinst.h"
28#include "aqua/saldata.hxx"
29#include "aqua/salframe.h"
30#include "aqua/salmenu.h"
31#include "aqua/salnsmenu.h"
32
33#include "vcl/window.hxx"
34
35@implementation SalNSMenu
36-(id)initWithMenu: (AquaSalMenu*)pMenu
37{
38    mpMenu = pMenu;
39    return [super initWithTitle: [NSString string]];
40}
41
42-(void)menuNeedsUpdate: (NSMenu*)pMenu
43{
44    (void)pMenu;
45    YIELD_GUARD;
46
47    if( mpMenu )
48    {
49        const AquaSalFrame* pFrame = mpMenu->getFrame();
50        if( pFrame && AquaSalFrame::isAlive( pFrame ) )
51        {
52            SalMenuEvent aMenuEvt;
53            aMenuEvt.mnId   = 0;
54            aMenuEvt.mpMenu = mpMenu->mpVCLMenu;
55            if( aMenuEvt.mpMenu )
56            {
57                pFrame->CallCallback(SALEVENT_MENUACTIVATE, &aMenuEvt);
58                pFrame->CallCallback(SALEVENT_MENUDEACTIVATE, &aMenuEvt);
59            }
60            else
61                DBG_ERROR( "unconnected menu" );
62        }
63    }
64}
65
66-(void)setSalMenu: (AquaSalMenu*)pMenu
67{
68    mpMenu = pMenu;
69}
70@end
71
72@implementation SalNSMenuItem
73-(id)initWithMenuItem: (AquaSalMenuItem*)pMenuItem
74{
75    mpMenuItem = pMenuItem;
76    id ret = [super initWithTitle: [NSString string]
77                    action: @selector(menuItemTriggered:)
78                    keyEquivalent: [NSString string]];
79    [ret setTarget: self];
80    return ret;
81}
82-(void)menuItemTriggered: (id)aSender
83{
84    (void)aSender;
85    YIELD_GUARD;
86
87    const AquaSalFrame* pFrame = mpMenuItem->mpParentMenu ? mpMenuItem->mpParentMenu->getFrame() : NULL;
88    if( pFrame && AquaSalFrame::isAlive( pFrame ) && ! pFrame->GetWindow()->IsInModalMode() )
89    {
90        SalMenuEvent aMenuEvt( mpMenuItem->mnId, mpMenuItem->mpVCLMenu );
91        pFrame->CallCallback(SALEVENT_MENUCOMMAND, &aMenuEvt);
92    }
93    else if( mpMenuItem->mpVCLMenu )
94    {
95        // if an item from submenu was selected. the corresponding Window does not exist because
96        // we use native popup menus, so we have to set the selected menuitem directly
97        // incidentally this of course works for top level popup menus, too
98        PopupMenu * pPopupMenu = dynamic_cast<PopupMenu *>(mpMenuItem->mpVCLMenu);
99        if( pPopupMenu )
100        {
101            // FIXME: revise this ugly code
102
103            // select handlers in vcl are dispatch on the original menu
104            // if not consumed by the select handler of the current menu
105            // however since only the starting menu ever came into Execute
106            // the hierarchy is not build up. Workaround this by getting
107            // the menu it should have been
108
109            // get started from hierarchy in vcl menus
110            AquaSalMenu* pParentMenu = mpMenuItem->mpParentMenu;
111            Menu* pCurMenu = mpMenuItem->mpVCLMenu;
112            while( pParentMenu && pParentMenu->mpVCLMenu )
113            {
114                pCurMenu = pParentMenu->mpVCLMenu;
115                pParentMenu = pParentMenu->mpParentSalMenu;
116            }
117
118            pPopupMenu->SetSelectedEntry( mpMenuItem->mnId );
119            pPopupMenu->ImplSelectWithStart( pCurMenu );
120        }
121        else
122            DBG_ERROR( "menubar item without frame !" );
123    }
124}
125@end
126
127@implementation OOStatusItemView
128-(void)drawRect: (NSRect)aRect
129{
130    NSGraphicsContext* pContext = [NSGraphicsContext currentContext];
131    [pContext saveGraphicsState];
132    [SalData::getStatusItem() drawStatusBarBackgroundInRect: aRect withHighlight: NO];
133    if( AquaSalMenu::pCurrentMenuBar )
134    {
135        const std::vector< AquaSalMenu::MenuBarButtonEntry >& rButtons( AquaSalMenu::pCurrentMenuBar->getButtons() );
136        NSRect aFrame = [self frame];
137        NSRect aImgRect = { { 2, 0 }, { 0, 0 } };
138        for( size_t i = 0; i < rButtons.size(); ++i )
139        {
140            const Size aPixSize = rButtons[i].maButton.maImage.GetSizePixel();
141            const NSRect aFromRect = { NSZeroPoint, NSMakeSize( aPixSize.Width(), aPixSize.Height()) };
142            aImgRect.origin.y = floor((aFrame.size.height - aFromRect.size.height)/2);
143            aImgRect.size = aFromRect.size;
144            if( rButtons[i].mpNSImage )
145                [rButtons[i].mpNSImage drawInRect: aImgRect fromRect: aFromRect operation: NSCompositeSourceOver fraction: 1.0];
146            aImgRect.origin.x += aFromRect.size.width + 2;
147        }
148    }
149    [pContext restoreGraphicsState];
150}
151
152-(void)mouseUp: (NSEvent *)pEvent
153{
154    /* check if button goes up inside one of our status buttons */
155    if( AquaSalMenu::pCurrentMenuBar )
156    {
157        const std::vector< AquaSalMenu::MenuBarButtonEntry >& rButtons( AquaSalMenu::pCurrentMenuBar->getButtons() );
158        NSRect aFrame = [self frame];
159        NSRect aImgRect = { { 2, 0 }, { 0, 0 } };
160        NSPoint aMousePt = [pEvent locationInWindow];
161        for( size_t i = 0; i < rButtons.size(); ++i )
162        {
163            const Size aPixSize = rButtons[i].maButton.maImage.GetSizePixel();
164            const NSRect aFromRect = { NSZeroPoint, NSMakeSize( aPixSize.Width(), aPixSize.Height()) };
165            aImgRect.origin.y = (aFrame.size.height - aFromRect.size.height)/2;
166            aImgRect.size = aFromRect.size;
167            if( aMousePt.x >= aImgRect.origin.x && aMousePt.x <= (aImgRect.origin.x+aImgRect.size.width) &&
168                aMousePt.y >= aImgRect.origin.y && aMousePt.y <= (aImgRect.origin.y+aImgRect.size.height) )
169            {
170                if( AquaSalMenu::pCurrentMenuBar->mpFrame && AquaSalFrame::isAlive( AquaSalMenu::pCurrentMenuBar->mpFrame ) )
171                {
172                    SalMenuEvent aMenuEvt( rButtons[i].maButton.mnId, AquaSalMenu::pCurrentMenuBar->mpVCLMenu );
173                    AquaSalMenu::pCurrentMenuBar->mpFrame->CallCallback(SALEVENT_MENUBUTTONCOMMAND, &aMenuEvt);
174                }
175                return;
176            }
177
178            aImgRect.origin.x += aFromRect.size.width + 2;
179        }
180    }
181}
182
183-(void)layout
184{
185    NSStatusBar* pStatBar = [NSStatusBar systemStatusBar];
186    NSSize aSize = { 0, [pStatBar thickness] };
187    [self removeAllToolTips];
188    if( AquaSalMenu::pCurrentMenuBar )
189    {
190        const std::vector< AquaSalMenu::MenuBarButtonEntry >& rButtons( AquaSalMenu::pCurrentMenuBar->getButtons() );
191        if( ! rButtons.empty() )
192        {
193            aSize.width = 2;
194            for( size_t i = 0; i < rButtons.size(); ++i )
195            {
196                const Size aPixSize = rButtons[i].maButton.maImage.GetSizePixel();
197                const int nY = floor( aSize.height - aPixSize.Height() ) / 2;
198                NSRect aImgRect = NSMakeRect( aSize.width, nY, aPixSize.Width(), aPixSize.Height());
199                if( rButtons[i].mpToolTipString )
200                    [self addToolTipRect: aImgRect owner: rButtons[i].mpToolTipString userData: NULL];
201                aSize.width += 2 + aImgRect.size.width;
202            }
203        }
204    }
205    [self setFrameSize: aSize];
206}
207@end
208
209
210