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