xref: /trunk/main/vcl/aqua/source/window/salnsmenu.mm (revision 79aad27f)
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            NSRect aFromRect = { { 0, 0 },
141                                 { rButtons[i].maButton.maImage.GetSizePixel().Width(),
142                                   rButtons[i].maButton.maImage.GetSizePixel().Height() } };
143            aImgRect.origin.y = floor((aFrame.size.height - aFromRect.size.height)/2);
144            aImgRect.size = aFromRect.size;
145            if( rButtons[i].mpNSImage )
146                [rButtons[i].mpNSImage drawInRect: aImgRect fromRect: aFromRect operation: NSCompositeSourceOver fraction: 1.0];
147            aImgRect.origin.x += aFromRect.size.width + 2;
148        }
149    }
150    [pContext restoreGraphicsState];
151}
152
153-(void)mouseUp: (NSEvent *)pEvent
154{
155    /* check if button goes up inside one of our status buttons */
156    if( AquaSalMenu::pCurrentMenuBar )
157    {
158        const std::vector< AquaSalMenu::MenuBarButtonEntry >& rButtons( AquaSalMenu::pCurrentMenuBar->getButtons() );
159        NSRect aFrame = [self frame];
160        NSRect aImgRect = { { 2, 0 }, { 0, 0 } };
161        NSPoint aMousePt = [pEvent locationInWindow];
162        for( size_t i = 0; i < rButtons.size(); ++i )
163        {
164            NSRect aFromRect = { { 0, 0 },
165                                 { rButtons[i].maButton.maImage.GetSizePixel().Width(),
166                                   rButtons[i].maButton.maImage.GetSizePixel().Height() } };
167            aImgRect.origin.y = (aFrame.size.height - aFromRect.size.height)/2;
168            aImgRect.size = aFromRect.size;
169            if( aMousePt.x >= aImgRect.origin.x && aMousePt.x <= (aImgRect.origin.x+aImgRect.size.width) &&
170                aMousePt.y >= aImgRect.origin.y && aMousePt.y <= (aImgRect.origin.y+aImgRect.size.height) )
171            {
172                if( AquaSalMenu::pCurrentMenuBar->mpFrame && AquaSalFrame::isAlive( AquaSalMenu::pCurrentMenuBar->mpFrame ) )
173                {
174                    SalMenuEvent aMenuEvt( rButtons[i].maButton.mnId, AquaSalMenu::pCurrentMenuBar->mpVCLMenu );
175                    AquaSalMenu::pCurrentMenuBar->mpFrame->CallCallback(SALEVENT_MENUBUTTONCOMMAND, &aMenuEvt);
176                }
177                return;
178            }
179
180            aImgRect.origin.x += aFromRect.size.width + 2;
181        }
182    }
183}
184
185-(void)layout
186{
187    NSStatusBar* pStatBar = [NSStatusBar systemStatusBar];
188    NSSize aSize = { 0, [pStatBar thickness] };
189    [self removeAllToolTips];
190    if( AquaSalMenu::pCurrentMenuBar )
191    {
192        const std::vector< AquaSalMenu::MenuBarButtonEntry >& rButtons( AquaSalMenu::pCurrentMenuBar->getButtons() );
193        if( ! rButtons.empty() )
194        {
195            aSize.width = 2;
196            for( size_t i = 0; i < rButtons.size(); ++i )
197            {
198                NSRect aImgRect = { { aSize.width, floor((aSize.height-rButtons[i].maButton.maImage.GetSizePixel().Height())/2) },
199                                     { rButtons[i].maButton.maImage.GetSizePixel().Width(),
200                                       rButtons[i].maButton.maImage.GetSizePixel().Height() } };
201                if( rButtons[i].mpToolTipString )
202                    [self addToolTipRect: aImgRect owner: rButtons[i].mpToolTipString userData: NULL];
203                aSize.width += 2 + aImgRect.size.width;
204            }
205        }
206    }
207    [self setFrameSize: aSize];
208}
209@end
210
211
212