~hikiko/nux/arb-srgba-shader

« back to all changes in this revision

Viewing changes to Nux/MenuBar.cpp

  • Committer: Neil Jagdish Patel
  • Date: 2010-09-02 03:28:11 UTC
  • Revision ID: neil.patel@canonical.com-20100902032811-i2m18tfb6pkasnvt
Remove Win EOL chars

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
 */
21
21
 
22
22
 
23
 
#include "Nux.h"
24
 
#include "WindowCompositor.h"
25
 
#include "HLayout.h"
26
 
#include "MenuBar.h"
27
 
 
28
 
NAMESPACE_BEGIN_GUI
29
 
 
30
 
static const UINT MENU_MINIMUM_WIDTH = 10;
31
 
static const UINT MENU_MINIMUM_HEIGHT = 16;
32
 
 
33
 
static const UINT MENUBAR_ICON_WIDTH = 24;
34
 
static const UINT MENUBAR_ICON_HEIGHT = 24;
35
 
 
36
 
IMPLEMENT_ROOT_OBJECT_TYPE(MenuBarItem);
37
 
IMPLEMENT_OBJECT_TYPE(MenuBar);
38
 
 
39
 
MenuBarItem::MenuBarItem()
40
 
{
41
 
    area = smptr(CoreArea)(new CoreArea());
42
 
    icon = 0;
43
 
}
44
 
 
45
 
MenuBarItem::~MenuBarItem()
46
 
{
47
 
    menu = smptr(MenuPage)(0);
48
 
    area = smptr(CoreArea)(0);
49
 
}
50
 
 
51
 
MenuBar::MenuBar()
52
 
:   m_MenuIsActive(false)
53
 
//,   m_CurrentMenu(0)
54
 
,   m_IsOpeningMenu(false)
55
 
,   m_MenuBarWindow(0)
56
 
57
 
    m_hlayout = smptr(HLayout)(new HLayout());
58
 
    m_hlayout->SetHorizontalInternalMargin(4);
59
 
    m_hlayout->SetHorizontalExternalMargin(2);
60
 
 
61
 
    SetMinimumSize(24, 24);
62
 
    SetMaximumSize(BASEOBJECT_MAXWIDTH, 24);
63
 
    setGeometry(Geometry(0, 0, 200, 20));
64
 
 
65
 
    m_hlayout->SetHorizontalInternalMargin(4);
66
 
    m_hlayout->SetVerticalExternalMargin(0);
67
 
    m_hlayout->SetContentStacking(eStackLeft);
68
 
    SetCompositionLayout(m_hlayout);
69
 
}
70
 
 
71
 
MenuBar::~MenuBar()
72
 
{
73
 
    if(m_CurrentMenu.IsValid())
74
 
    {
75
 
//         m_CurrentMenu->area->OnMouseEnter.clear();
76
 
//         m_CurrentMenu->area->OnMouseEnter.clear();
77
 
//         m_CurrentMenu->area->OnMouseLeave.clear();
78
 
//         m_CurrentMenu->area->OnMouseDown.clear();
79
 
//         m_CurrentMenu->area->OnMouseDrag.clear();
80
 
//         m_CurrentMenu->area->OnMouseUp.clear();
81
 
    }
82
 
 
83
 
    std::list< smptr(MenuBarItem) >::iterator it;
84
 
    for(it = m_MenuBarItemList.begin(); it != m_MenuBarItemList.end(); it++)
85
 
    {
86
 
//         (*it)->area->OnMouseEnter.clear();
87
 
//         (*it)->area->OnMouseEnter.clear();
88
 
//         (*it)->area->OnMouseLeave.clear();
89
 
//         (*it)->area->OnMouseDown.clear();
90
 
//         (*it)->area->OnMouseDrag.clear();
91
 
//         (*it)->area->OnMouseUp.clear();
92
 
 
93
 
        (*it) = smptr(MenuBarItem)(0);
94
 
    }
95
 
    m_MenuBarItemList.clear();
96
 
}
97
 
 
98
 
long MenuBar::ProcessEvent(IEvent &ievent, long TraverseInfo, long ProcessEventInfo)
99
 
{
100
 
    long ret = TraverseInfo;
101
 
    long ProcEvInfo = 0;
102
 
 
103
 
    ret = TraverseInfo;  // <<---- never forget this
104
 
 
105
 
    std::list< smptr(MenuBarItem) >::iterator it;
106
 
    
107
 
    for(it = m_MenuBarItemList.begin(); it != m_MenuBarItemList.end(); it++)
108
 
    {
109
 
        (*it)->menu->m_MenuWindow = m_MenuBarWindow;
110
 
        ret = (*it)->area->OnEvent(ievent, ret, ProcessEventInfo);
111
 
    }
112
 
 
113
 
    if(ievent.e_event == INL_MOUSE_PRESSED)
114
 
    {
115
 
        bool mouse_down_on_menu_item = false;
116
 
        if(m_MenuIsActive == true)
117
 
        {
118
 
            for(it = m_MenuBarItemList.begin(); it != m_MenuBarItemList.end(); it++)
119
 
            {
120
 
                if((*it)->area->IsMouseInside())
121
 
                {
122
 
                    mouse_down_on_menu_item = true;
123
 
                    break;
124
 
                }
125
 
            }
126
 
            if(mouse_down_on_menu_item == false)
127
 
            {
128
 
                if(m_CurrentMenu->menu->TestMouseDown() == false)
129
 
                {
130
 
                    RecvSigTerminateMenuCascade();
131
 
                }
132
 
            }
133
 
        }
134
 
    }
135
 
    
136
 
 
137
 
    // PostProcessEvent2 must always have its last parameter set to 0
138
 
    // because the m_BackgroundArea is the real physical limit of the window.
139
 
    // So the previous test about IsPointInside do not prevail over m_BackgroundArea 
140
 
    // testing the event by itself.
141
 
    ret = PostProcessEvent2(ievent, ret, 0);
142
 
    return ret;
143
 
}
144
 
 
145
 
void MenuBar::Draw(GraphicsContext& GfxContext, bool force_draw)
146
 
{
147
 
    Geometry base = GetGeometry();
148
 
    GfxContext.PushClippingRectangle(base);
149
 
 
150
 
    Geometry item_geometry;
151
 
    std::list< smptr(MenuBarItem) >::iterator it;
152
 
    for(it = m_MenuBarItemList.begin(); it != m_MenuBarItemList.end(); it++)
153
 
    {
154
 
        smptr(CoreArea) area = (*it)->area;
155
 
        item_geometry = area->GetGeometry();
156
 
        if(area->IsMouseInside())
157
 
        {
158
 
            
159
 
            gPainter.PaintBackground(GfxContext, item_geometry);
160
 
            if(!m_MenuIsActive)
161
 
            {
162
 
                gPainter.Paint2DQuadColor(GfxContext, item_geometry, Color(0xFF000000));
163
 
                //gPainter.PaintShape(GfxContext, item_geometry, Color(0xFF000000), eSHAPE_CORNER_ROUND2);
164
 
            }
165
 
            else
166
 
            {
167
 
                gPainter.Paint2DQuadColor(GfxContext, item_geometry, Color(0xFF000000));
168
 
                //gPainter.PaintShapeCorner(GfxContext, item_geometry, Color(0xFF000000), eSHAPE_CORNER_ROUND2,
169
 
                //eCornerTopLeft|eCornerTopRight, false);
170
 
            }
171
 
 
172
 
            if((*it)->icon)
173
 
            {
174
 
                GfxContext.GetRenderStates().SetBlend(TRUE, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
175
 
                GfxContext.GetRenderStates().SetColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
176
 
                gPainter.Draw2DTexture(GfxContext, (*it)->icon, item_geometry.x, item_geometry.y);
177
 
                GfxContext.GetRenderStates().SetColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
178
 
                GfxContext.GetRenderStates().SetBlend(GL_FALSE);
179
 
            }
180
 
            else
181
 
            {
182
 
                gPainter.PaintTextLineStatic(GfxContext, GetFont(), item_geometry, area->GetBaseString().GetTCharPtr(), GetTextColor(), true, eAlignTextCenter);
183
 
            }
184
 
        }
185
 
        else
186
 
        {
187
 
            gPainter.PaintBackground(GfxContext, item_geometry);
188
 
 
189
 
            if((*it)->icon)
190
 
            {
191
 
                GfxContext.GetRenderStates().SetColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
192
 
                GfxContext.GetRenderStates().SetBlend(TRUE, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
193
 
                gPainter.Draw2DTexture(GfxContext, (*it)->icon, item_geometry.x, item_geometry.y);
194
 
                GfxContext.GetRenderStates().SetColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
195
 
                GfxContext.GetRenderStates().SetBlend(GL_FALSE);
196
 
            }
197
 
            else
198
 
            {
199
 
                gPainter.PaintTextLineStatic(GfxContext, GetFont(), item_geometry, area->GetBaseString().GetTCharPtr(), GetTextColor(), true, eAlignTextCenter);
200
 
            }
201
 
        }
202
 
    }
203
 
    if(m_MenuIsActive)
204
 
    {
205
 
        smptr(CoreArea) area(m_CurrentMenu->area);
206
 
        item_geometry = area->GetGeometry();
207
 
        gPainter.PaintBackground(GfxContext, item_geometry);
208
 
        gPainter.Paint2DQuadColor(GfxContext, item_geometry, Color(0xFF000000));
209
 
        //gPainter.PaintShapeCorner(GfxContext, item_geometry, Color(0xFF000000), eSHAPE_CORNER_ROUND2, eCornerTopLeft|eCornerTopRight, true);
210
 
 
211
 
        if(m_CurrentMenu->icon)
212
 
        {
213
 
            GfxContext.GetRenderStates().SetBlend(TRUE, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
214
 
            GfxContext.GetRenderStates().SetColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
215
 
            gPainter.Draw2DTexture(GfxContext, m_CurrentMenu->icon, item_geometry.x, item_geometry.y);
216
 
            GfxContext.GetRenderStates().SetColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
217
 
            GfxContext.GetRenderStates().SetBlend(GL_FALSE);
218
 
        }
219
 
        else
220
 
        {
221
 
            gPainter.PaintTextLineStatic(GfxContext, GetFont(), item_geometry, area->GetBaseString().GetTCharPtr(), GetTextColor(), true, eAlignTextCenter);
222
 
        }
223
 
    }
224
 
    GfxContext.PopClippingRectangle();
225
 
}
226
 
 
227
 
void MenuBar::DrawContent(GraphicsContext& GfxContext, bool force_draw)
228
 
{
229
 
    GfxContext.PushClippingRectangle(GetGeometry());
230
 
    GfxContext.PopClippingRectangle();
231
 
}
232
 
 
233
 
void MenuBar::PostDraw(GraphicsContext& GfxContext, bool force_draw)
234
 
{
235
 
 
236
 
}
237
 
 
238
 
void MenuBar::AddMenu(const TCHAR* MenuLabel, smptr(MenuPage) menu)
239
 
{
240
 
    AddMenu(MenuLabel, menu, 0);
241
 
}
242
 
 
243
 
void MenuBar::AddMenu(const TCHAR* MenuLabel, smptr(MenuPage) menu, NTexture *icon)
244
 
{
245
 
    // Need to add INL_RETURN_IF_TRUE, INL_RETURN_IF_FALSE
246
 
    INL_RETURN_IF_TRUE(menu.IsNull());
247
 
 
248
 
    smptr(MenuBarItem) menubar_item(new MenuBarItem());
249
 
 
250
 
    menu->m_IsTopOfMenuChain = true;
251
 
    menubar_item->area->SetBaseString(MenuLabel);
252
 
    menubar_item->menu = menu;
253
 
    menubar_item->icon = icon;
254
 
 
255
 
    m_MenuBarItemList.push_back(menubar_item);
256
 
    //menubar_item->area->SetMinimumSize(DEFAULT_WIDGET_WIDTH, 40);
257
 
    if(!icon)
258
 
    {
259
 
        menubar_item->area->SetMinimumSize(Max(MENU_MINIMUM_WIDTH, (UINT)(10 + GetFont()->GetStringWidth(MenuLabel))), Max(MENU_MINIMUM_WIDTH, (UINT)16));
260
 
    }
261
 
    else
262
 
    {
263
 
        menubar_item->area->SetMinMaxSize(MENUBAR_ICON_WIDTH, MENUBAR_ICON_HEIGHT);
264
 
    }
265
 
 
266
 
    menubar_item->area->OnMouseEnter.connect(sigc::bind( sigc::mem_fun(this, &MenuBar::EmitItemMouseEnter), weaksmptr(MenuBarItem)(menubar_item)));
267
 
    menubar_item->area->OnMouseLeave.connect(sigc::bind( sigc::mem_fun(this, &MenuBar::EmitItemMouseLeave), weaksmptr(MenuBarItem)(menubar_item)));
268
 
    menubar_item->area->OnMouseDown.connect(sigc::bind( sigc::mem_fun(this, &MenuBar::EmitItemMouseDown), weaksmptr(MenuBarItem)(menubar_item)));
269
 
    menubar_item->area->OnMouseDrag.connect(sigc::bind( sigc::mem_fun(this, &MenuBar::RecvItemMouseDrag), weaksmptr(MenuBarItem)(menubar_item)));
270
 
    menubar_item->area->OnMouseUp.connect(sigc::bind( sigc::mem_fun(this, &MenuBar::EmitItemMouseUp), weaksmptr(MenuBarItem)(menubar_item)));
271
 
 
272
 
    menubar_item->menu->SetParentMenu(smptr(MenuPage)(0));
273
 
    menubar_item->menu->sigActionTriggered.connect(sigc::mem_fun(this, &MenuBar::RecvSigActionTriggered));
274
 
    menubar_item->menu->sigTerminateMenuCascade.connect(sigc::mem_fun(this, &MenuBar::RecvSigTerminateMenuCascade));
275
 
    menubar_item->menu->sigMouseDownOutsideMenuCascade.connect(sigc::mem_fun(this, &MenuBar::RecvSigMouseDownOutsideMenuCascade));
276
 
 
277
 
    m_hlayout->AddActiveInterfaceObject(menubar_item->area, 0, eCenter);
278
 
    GetGraphicsThread()->ComputeElementLayout(m_hlayout);
279
 
}
280
 
 
281
 
void MenuBar::EmitItemMouseEnter(int x, int y, unsigned long button_flags, unsigned long key_flags, weaksmptr(MenuBarItem) menubar_item)
282
 
{
283
 
    if(m_MenuIsActive)
284
 
    {
285
 
        if(m_CurrentMenu.IsValid() && (m_CurrentMenu->menu != menubar_item->menu))
286
 
            m_CurrentMenu->menu->StopMenu(0, 0);
287
 
 
288
 
        Geometry geo = menubar_item->menu->GetGeometry();
289
 
        menubar_item->menu->m_MenuWindow = m_MenuBarWindow;
290
 
        menubar_item->menu->StartMenu(menubar_item->area->GetBaseX(), 
291
 
            menubar_item->area->GetBaseY() + menubar_item->area->GetBaseHeight(), 0, 0);
292
 
 
293
 
        m_CurrentMenu = menubar_item;
294
 
 
295
 
        m_IsOpeningMenu = true;
296
 
    }
297
 
    NeedRedraw();
298
 
}
299
 
 
300
 
void MenuBar::EmitItemMouseLeave(int x, int y, unsigned long button_flags, unsigned long key_flags, weaksmptr(MenuBarItem) menubar_item)
301
 
{
302
 
    NeedRedraw();
303
 
}
304
 
void MenuBar::EmitItemMouseDown(int x, int y, unsigned long button_flags, unsigned long key_flags, weaksmptr(MenuBarItem) menubar_item)
305
 
{
306
 
    m_MenuBarWindow = GetThreadWindowCompositor().GetCurrentWindow();
307
 
    if(m_MenuIsActive == false)
308
 
    {
309
 
        // Open the corresponding MenuPage
310
 
        if(m_CurrentMenu.IsValid())
311
 
        {
312
 
            // This should never happen
313
 
            nuxAssert(0);
314
 
            m_CurrentMenu->menu->StopMenu();
315
 
        }
316
 
 
317
 
        m_MenuIsActive = true;
318
 
        m_CurrentMenu = menubar_item;
319
 
        m_CurrentMenu->menu->m_MenuWindow = m_MenuBarWindow;
320
 
        m_IsOpeningMenu = true;
321
 
 
322
 
        //m_CurrentMenu->area->ForceStopFocus(0, 0);
323
 
        m_CurrentMenu->menu->StartMenu(menubar_item->area->GetBaseX(), 
324
 
            menubar_item->area->GetBaseY() + menubar_item->area->GetBaseHeight(), 0, 0);
325
 
    }
326
 
    else
327
 
    {
328
 
        // If the mouse up that follows happen inside the area, then it is going to close the menu.
329
 
        m_IsOpeningMenu = false;
330
 
    }
331
 
    NeedRedraw();
332
 
}
333
 
 
334
 
void MenuBar::EmitItemMouseUp(int x, int y, unsigned long button_flags, unsigned long key_flags, weaksmptr(MenuBarItem) menubar_item)
335
 
{
336
 
    if(m_MenuIsActive)
337
 
    {
338
 
        if(m_CurrentMenu->area->IsMouseInside())
339
 
        {
340
 
            if(m_IsOpeningMenu == false)
341
 
            {
342
 
                // close the MenuPage that is Open
343
 
                if(m_CurrentMenu.IsValid())
344
 
                    m_CurrentMenu->menu->StopMenu(0, 0);
345
 
                m_MenuIsActive = false;
346
 
                m_CurrentMenu = smptr(MenuBarItem)(0);
347
 
            }
348
 
            else
349
 
            {
350
 
                // The MousePress before this MouseRelease, caused the MenuPage to open.
351
 
                // Set m_IsOpeningMenu so the next mouse release will close the menu.
352
 
                m_IsOpeningMenu = false;
353
 
            }
354
 
        }
355
 
        else
356
 
        {
357
 
            bool hit_inside_a_menu = false;
358
 
            bool b = m_CurrentMenu->menu->TestMouseUp(x, y, button_flags, key_flags, hit_inside_a_menu);
359
 
            if(b || (hit_inside_a_menu == false))
360
 
            {
361
 
                RecvSigTerminateMenuCascade();
362
 
            }
363
 
        }
364
 
    }
365
 
    NeedRedraw();
366
 
}
367
 
 
368
 
void MenuBar::RecvItemMouseDrag(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags, weaksmptr(MenuBarItem) menubar_item)
369
 
{
370
 
    // Transition between one menu bar item to another
371
 
    if(GetThreadWindowCompositor().GetMouseFocusArea() == menubar_item->area)
372
 
    {
373
 
        if(!menubar_item->area->IsMouseInside())  // can also test GetThreadWindowCompositor().GetMouseOverArea() != &menubar_item->area
374
 
        {
375
 
            &menubar_item->area;
376
 
            std::list< smptr(MenuBarItem) >::iterator it;
377
 
            // compute window coordinates x and y;
378
 
            int winx = menubar_item->area->GetBaseX() + x; 
379
 
            int winy = menubar_item->area->GetBaseY() + y;
380
 
            for(it = m_MenuBarItemList.begin(); it != m_MenuBarItemList.end(); it++)
381
 
            {
382
 
                smptr(CoreArea) area = (*it)->area;
383
 
                Geometry geometry = area->GetGeometry();
384
 
                if(geometry.IsPointInside(winx, winy))
385
 
                {
386
 
                    // Close the menu below menubar_item (the one that has the focus
387
 
                    menubar_item->area->ForceStopFocus(0, 0);
388
 
 
389
 
                    // EmitItemMouseEnter is going to open the menu below (*it)
390
 
                    {
391
 
                        EmitItemMouseEnter(winx, winy, button_flags, key_flags, (*it));
392
 
                        m_IsOpeningMenu = true;
393
 
                        area->ForceStartFocus(0, 0);
394
 
 
395
 
                        GetThreadWindowCompositor().SetMouseFocusArea(area);
396
 
                        GetThreadWindowCompositor().SetMouseOverArea(area);
397
 
                    }
398
 
                    
399
 
                    break;
400
 
                }
401
 
            }
402
 
        }
403
 
    }
404
 
}
405
 
 
406
 
void MenuBar::RecvSigActionTriggered(smptr(MenuPage) menu, const smptr(ActionItem) action)
407
 
{
408
 
    m_MenuIsActive = false;
409
 
    if(m_CurrentMenu.IsValid())
410
 
    {
411
 
        m_CurrentMenu->menu->StopMenu();
412
 
        NeedRedraw();
413
 
    }
414
 
    m_CurrentMenu = smptr(MenuBarItem)(0);
415
 
    m_IsOpeningMenu = false;
416
 
 
417
 
    // You can do something if you want with the menu* and the action*
418
 
}
419
 
 
420
 
 
421
 
void MenuBar::RecvSigTerminateMenuCascade()
422
 
{
423
 
    m_MenuIsActive = false;
424
 
    if(m_CurrentMenu.IsValid())
425
 
    {
426
 
        m_CurrentMenu->menu->StopMenu();
427
 
    }
428
 
    m_CurrentMenu = smptr(MenuBarItem)(0);
429
 
    m_IsOpeningMenu = false;
430
 
 
431
 
    NeedRedraw();
432
 
}
433
 
 
434
 
void MenuBar::RecvSigMouseDownOutsideMenuCascade(smptr(MenuPage) menu, int x, int y)
435
 
{
436
 
    Geometry geometry;
437
 
    std::list< smptr(MenuBarItem) >::iterator it;
438
 
    UBOOL TerminateMenuCascade = 1;
439
 
    for(it = m_MenuBarItemList.begin(); it != m_MenuBarItemList.end(); it++)
440
 
    {
441
 
        smptr(CoreArea) area = (*it)->area;
442
 
        geometry = area->GetGeometry();
443
 
        if(geometry.IsPointInside(x, y))
444
 
        {
445
 
            // The event landed on one of the MenuBar item.
446
 
            // Do nothing. This will be handled in the ProcessEvent of the MenuBar item where the mouse down landed.
447
 
            TerminateMenuCascade = 0;
448
 
            break;
449
 
        }
450
 
    }
451
 
    if(TerminateMenuCascade)
452
 
        RecvSigTerminateMenuCascade();
453
 
}
454
 
 
455
 
 
456
 
NAMESPACE_END_GUI
 
23
#include "Nux.h"
 
24
#include "WindowCompositor.h"
 
25
#include "HLayout.h"
 
26
#include "MenuBar.h"
 
27
 
 
28
NAMESPACE_BEGIN_GUI
 
29
 
 
30
static const UINT MENU_MINIMUM_WIDTH = 10;
 
31
static const UINT MENU_MINIMUM_HEIGHT = 16;
 
32
 
 
33
static const UINT MENUBAR_ICON_WIDTH = 24;
 
34
static const UINT MENUBAR_ICON_HEIGHT = 24;
 
35
 
 
36
IMPLEMENT_ROOT_OBJECT_TYPE(MenuBarItem);
 
37
IMPLEMENT_OBJECT_TYPE(MenuBar);
 
38
 
 
39
MenuBarItem::MenuBarItem()
 
40
{
 
41
    area = smptr(CoreArea)(new CoreArea());
 
42
    icon = 0;
 
43
}
 
44
 
 
45
MenuBarItem::~MenuBarItem()
 
46
{
 
47
    menu = smptr(MenuPage)(0);
 
48
    area = smptr(CoreArea)(0);
 
49
}
 
50
 
 
51
MenuBar::MenuBar()
 
52
:   m_MenuIsActive(false)
 
53
//,   m_CurrentMenu(0)
 
54
,   m_IsOpeningMenu(false)
 
55
,   m_MenuBarWindow(0)
 
56
 
57
    m_hlayout = smptr(HLayout)(new HLayout());
 
58
    m_hlayout->SetHorizontalInternalMargin(4);
 
59
    m_hlayout->SetHorizontalExternalMargin(2);
 
60
 
 
61
    SetMinimumSize(24, 24);
 
62
    SetMaximumSize(BASEOBJECT_MAXWIDTH, 24);
 
63
    setGeometry(Geometry(0, 0, 200, 20));
 
64
 
 
65
    m_hlayout->SetHorizontalInternalMargin(4);
 
66
    m_hlayout->SetVerticalExternalMargin(0);
 
67
    m_hlayout->SetContentStacking(eStackLeft);
 
68
    SetCompositionLayout(m_hlayout);
 
69
}
 
70
 
 
71
MenuBar::~MenuBar()
 
72
{
 
73
    if(m_CurrentMenu.IsValid())
 
74
    {
 
75
//         m_CurrentMenu->area->OnMouseEnter.clear();
 
76
//         m_CurrentMenu->area->OnMouseEnter.clear();
 
77
//         m_CurrentMenu->area->OnMouseLeave.clear();
 
78
//         m_CurrentMenu->area->OnMouseDown.clear();
 
79
//         m_CurrentMenu->area->OnMouseDrag.clear();
 
80
//         m_CurrentMenu->area->OnMouseUp.clear();
 
81
    }
 
82
 
 
83
    std::list< smptr(MenuBarItem) >::iterator it;
 
84
    for(it = m_MenuBarItemList.begin(); it != m_MenuBarItemList.end(); it++)
 
85
    {
 
86
//         (*it)->area->OnMouseEnter.clear();
 
87
//         (*it)->area->OnMouseEnter.clear();
 
88
//         (*it)->area->OnMouseLeave.clear();
 
89
//         (*it)->area->OnMouseDown.clear();
 
90
//         (*it)->area->OnMouseDrag.clear();
 
91
//         (*it)->area->OnMouseUp.clear();
 
92
 
 
93
        (*it) = smptr(MenuBarItem)(0);
 
94
    }
 
95
    m_MenuBarItemList.clear();
 
96
}
 
97
 
 
98
long MenuBar::ProcessEvent(IEvent &ievent, long TraverseInfo, long ProcessEventInfo)
 
99
{
 
100
    long ret = TraverseInfo;
 
101
    long ProcEvInfo = 0;
 
102
 
 
103
    ret = TraverseInfo;  // <<---- never forget this
 
104
 
 
105
    std::list< smptr(MenuBarItem) >::iterator it;
 
106
    
 
107
    for(it = m_MenuBarItemList.begin(); it != m_MenuBarItemList.end(); it++)
 
108
    {
 
109
        (*it)->menu->m_MenuWindow = m_MenuBarWindow;
 
110
        ret = (*it)->area->OnEvent(ievent, ret, ProcessEventInfo);
 
111
    }
 
112
 
 
113
    if(ievent.e_event == INL_MOUSE_PRESSED)
 
114
    {
 
115
        bool mouse_down_on_menu_item = false;
 
116
        if(m_MenuIsActive == true)
 
117
        {
 
118
            for(it = m_MenuBarItemList.begin(); it != m_MenuBarItemList.end(); it++)
 
119
            {
 
120
                if((*it)->area->IsMouseInside())
 
121
                {
 
122
                    mouse_down_on_menu_item = true;
 
123
                    break;
 
124
                }
 
125
            }
 
126
            if(mouse_down_on_menu_item == false)
 
127
            {
 
128
                if(m_CurrentMenu->menu->TestMouseDown() == false)
 
129
                {
 
130
                    RecvSigTerminateMenuCascade();
 
131
                }
 
132
            }
 
133
        }
 
134
    }
 
135
    
 
136
 
 
137
    // PostProcessEvent2 must always have its last parameter set to 0
 
138
    // because the m_BackgroundArea is the real physical limit of the window.
 
139
    // So the previous test about IsPointInside do not prevail over m_BackgroundArea 
 
140
    // testing the event by itself.
 
141
    ret = PostProcessEvent2(ievent, ret, 0);
 
142
    return ret;
 
143
}
 
144
 
 
145
void MenuBar::Draw(GraphicsContext& GfxContext, bool force_draw)
 
146
{
 
147
    Geometry base = GetGeometry();
 
148
    GfxContext.PushClippingRectangle(base);
 
149
 
 
150
    Geometry item_geometry;
 
151
    std::list< smptr(MenuBarItem) >::iterator it;
 
152
    for(it = m_MenuBarItemList.begin(); it != m_MenuBarItemList.end(); it++)
 
153
    {
 
154
        smptr(CoreArea) area = (*it)->area;
 
155
        item_geometry = area->GetGeometry();
 
156
        if(area->IsMouseInside())
 
157
        {
 
158
            
 
159
            gPainter.PaintBackground(GfxContext, item_geometry);
 
160
            if(!m_MenuIsActive)
 
161
            {
 
162
                gPainter.Paint2DQuadColor(GfxContext, item_geometry, Color(0xFF000000));
 
163
                //gPainter.PaintShape(GfxContext, item_geometry, Color(0xFF000000), eSHAPE_CORNER_ROUND2);
 
164
            }
 
165
            else
 
166
            {
 
167
                gPainter.Paint2DQuadColor(GfxContext, item_geometry, Color(0xFF000000));
 
168
                //gPainter.PaintShapeCorner(GfxContext, item_geometry, Color(0xFF000000), eSHAPE_CORNER_ROUND2,
 
169
                //eCornerTopLeft|eCornerTopRight, false);
 
170
            }
 
171
 
 
172
            if((*it)->icon)
 
173
            {
 
174
                GfxContext.GetRenderStates().SetBlend(TRUE, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
 
175
                GfxContext.GetRenderStates().SetColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
 
176
                gPainter.Draw2DTexture(GfxContext, (*it)->icon, item_geometry.x, item_geometry.y);
 
177
                GfxContext.GetRenderStates().SetColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
 
178
                GfxContext.GetRenderStates().SetBlend(GL_FALSE);
 
179
            }
 
180
            else
 
181
            {
 
182
                gPainter.PaintTextLineStatic(GfxContext, GetFont(), item_geometry, area->GetBaseString().GetTCharPtr(), GetTextColor(), true, eAlignTextCenter);
 
183
            }
 
184
        }
 
185
        else
 
186
        {
 
187
            gPainter.PaintBackground(GfxContext, item_geometry);
 
188
 
 
189
            if((*it)->icon)
 
190
            {
 
191
                GfxContext.GetRenderStates().SetColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
 
192
                GfxContext.GetRenderStates().SetBlend(TRUE, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
 
193
                gPainter.Draw2DTexture(GfxContext, (*it)->icon, item_geometry.x, item_geometry.y);
 
194
                GfxContext.GetRenderStates().SetColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
 
195
                GfxContext.GetRenderStates().SetBlend(GL_FALSE);
 
196
            }
 
197
            else
 
198
            {
 
199
                gPainter.PaintTextLineStatic(GfxContext, GetFont(), item_geometry, area->GetBaseString().GetTCharPtr(), GetTextColor(), true, eAlignTextCenter);
 
200
            }
 
201
        }
 
202
    }
 
203
    if(m_MenuIsActive)
 
204
    {
 
205
        smptr(CoreArea) area(m_CurrentMenu->area);
 
206
        item_geometry = area->GetGeometry();
 
207
        gPainter.PaintBackground(GfxContext, item_geometry);
 
208
        gPainter.Paint2DQuadColor(GfxContext, item_geometry, Color(0xFF000000));
 
209
        //gPainter.PaintShapeCorner(GfxContext, item_geometry, Color(0xFF000000), eSHAPE_CORNER_ROUND2, eCornerTopLeft|eCornerTopRight, true);
 
210
 
 
211
        if(m_CurrentMenu->icon)
 
212
        {
 
213
            GfxContext.GetRenderStates().SetBlend(TRUE, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
 
214
            GfxContext.GetRenderStates().SetColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
 
215
            gPainter.Draw2DTexture(GfxContext, m_CurrentMenu->icon, item_geometry.x, item_geometry.y);
 
216
            GfxContext.GetRenderStates().SetColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
 
217
            GfxContext.GetRenderStates().SetBlend(GL_FALSE);
 
218
        }
 
219
        else
 
220
        {
 
221
            gPainter.PaintTextLineStatic(GfxContext, GetFont(), item_geometry, area->GetBaseString().GetTCharPtr(), GetTextColor(), true, eAlignTextCenter);
 
222
        }
 
223
    }
 
224
    GfxContext.PopClippingRectangle();
 
225
}
 
226
 
 
227
void MenuBar::DrawContent(GraphicsContext& GfxContext, bool force_draw)
 
228
{
 
229
    GfxContext.PushClippingRectangle(GetGeometry());
 
230
    GfxContext.PopClippingRectangle();
 
231
}
 
232
 
 
233
void MenuBar::PostDraw(GraphicsContext& GfxContext, bool force_draw)
 
234
{
 
235
 
 
236
}
 
237
 
 
238
void MenuBar::AddMenu(const TCHAR* MenuLabel, smptr(MenuPage) menu)
 
239
{
 
240
    AddMenu(MenuLabel, menu, 0);
 
241
}
 
242
 
 
243
void MenuBar::AddMenu(const TCHAR* MenuLabel, smptr(MenuPage) menu, NTexture *icon)
 
244
{
 
245
    // Need to add INL_RETURN_IF_TRUE, INL_RETURN_IF_FALSE
 
246
    INL_RETURN_IF_TRUE(menu.IsNull());
 
247
 
 
248
    smptr(MenuBarItem) menubar_item(new MenuBarItem());
 
249
 
 
250
    menu->m_IsTopOfMenuChain = true;
 
251
    menubar_item->area->SetBaseString(MenuLabel);
 
252
    menubar_item->menu = menu;
 
253
    menubar_item->icon = icon;
 
254
 
 
255
    m_MenuBarItemList.push_back(menubar_item);
 
256
    //menubar_item->area->SetMinimumSize(DEFAULT_WIDGET_WIDTH, 40);
 
257
    if(!icon)
 
258
    {
 
259
        menubar_item->area->SetMinimumSize(Max(MENU_MINIMUM_WIDTH, (UINT)(10 + GetFont()->GetStringWidth(MenuLabel))), Max(MENU_MINIMUM_WIDTH, (UINT)16));
 
260
    }
 
261
    else
 
262
    {
 
263
        menubar_item->area->SetMinMaxSize(MENUBAR_ICON_WIDTH, MENUBAR_ICON_HEIGHT);
 
264
    }
 
265
 
 
266
    menubar_item->area->OnMouseEnter.connect(sigc::bind( sigc::mem_fun(this, &MenuBar::EmitItemMouseEnter), weaksmptr(MenuBarItem)(menubar_item)));
 
267
    menubar_item->area->OnMouseLeave.connect(sigc::bind( sigc::mem_fun(this, &MenuBar::EmitItemMouseLeave), weaksmptr(MenuBarItem)(menubar_item)));
 
268
    menubar_item->area->OnMouseDown.connect(sigc::bind( sigc::mem_fun(this, &MenuBar::EmitItemMouseDown), weaksmptr(MenuBarItem)(menubar_item)));
 
269
    menubar_item->area->OnMouseDrag.connect(sigc::bind( sigc::mem_fun(this, &MenuBar::RecvItemMouseDrag), weaksmptr(MenuBarItem)(menubar_item)));
 
270
    menubar_item->area->OnMouseUp.connect(sigc::bind( sigc::mem_fun(this, &MenuBar::EmitItemMouseUp), weaksmptr(MenuBarItem)(menubar_item)));
 
271
 
 
272
    menubar_item->menu->SetParentMenu(smptr(MenuPage)(0));
 
273
    menubar_item->menu->sigActionTriggered.connect(sigc::mem_fun(this, &MenuBar::RecvSigActionTriggered));
 
274
    menubar_item->menu->sigTerminateMenuCascade.connect(sigc::mem_fun(this, &MenuBar::RecvSigTerminateMenuCascade));
 
275
    menubar_item->menu->sigMouseDownOutsideMenuCascade.connect(sigc::mem_fun(this, &MenuBar::RecvSigMouseDownOutsideMenuCascade));
 
276
 
 
277
    m_hlayout->AddActiveInterfaceObject(menubar_item->area, 0, eCenter);
 
278
    GetGraphicsThread()->ComputeElementLayout(m_hlayout);
 
279
}
 
280
 
 
281
void MenuBar::EmitItemMouseEnter(int x, int y, unsigned long button_flags, unsigned long key_flags, weaksmptr(MenuBarItem) menubar_item)
 
282
{
 
283
    if(m_MenuIsActive)
 
284
    {
 
285
        if(m_CurrentMenu.IsValid() && (m_CurrentMenu->menu != menubar_item->menu))
 
286
            m_CurrentMenu->menu->StopMenu(0, 0);
 
287
 
 
288
        Geometry geo = menubar_item->menu->GetGeometry();
 
289
        menubar_item->menu->m_MenuWindow = m_MenuBarWindow;
 
290
        menubar_item->menu->StartMenu(menubar_item->area->GetBaseX(), 
 
291
            menubar_item->area->GetBaseY() + menubar_item->area->GetBaseHeight(), 0, 0);
 
292
 
 
293
        m_CurrentMenu = menubar_item;
 
294
 
 
295
        m_IsOpeningMenu = true;
 
296
    }
 
297
    NeedRedraw();
 
298
}
 
299
 
 
300
void MenuBar::EmitItemMouseLeave(int x, int y, unsigned long button_flags, unsigned long key_flags, weaksmptr(MenuBarItem) menubar_item)
 
301
{
 
302
    NeedRedraw();
 
303
}
 
304
void MenuBar::EmitItemMouseDown(int x, int y, unsigned long button_flags, unsigned long key_flags, weaksmptr(MenuBarItem) menubar_item)
 
305
{
 
306
    m_MenuBarWindow = GetThreadWindowCompositor().GetCurrentWindow();
 
307
    if(m_MenuIsActive == false)
 
308
    {
 
309
        // Open the corresponding MenuPage
 
310
        if(m_CurrentMenu.IsValid())
 
311
        {
 
312
            // This should never happen
 
313
            nuxAssert(0);
 
314
            m_CurrentMenu->menu->StopMenu();
 
315
        }
 
316
 
 
317
        m_MenuIsActive = true;
 
318
        m_CurrentMenu = menubar_item;
 
319
        m_CurrentMenu->menu->m_MenuWindow = m_MenuBarWindow;
 
320
        m_IsOpeningMenu = true;
 
321
 
 
322
        //m_CurrentMenu->area->ForceStopFocus(0, 0);
 
323
        m_CurrentMenu->menu->StartMenu(menubar_item->area->GetBaseX(), 
 
324
            menubar_item->area->GetBaseY() + menubar_item->area->GetBaseHeight(), 0, 0);
 
325
    }
 
326
    else
 
327
    {
 
328
        // If the mouse up that follows happen inside the area, then it is going to close the menu.
 
329
        m_IsOpeningMenu = false;
 
330
    }
 
331
    NeedRedraw();
 
332
}
 
333
 
 
334
void MenuBar::EmitItemMouseUp(int x, int y, unsigned long button_flags, unsigned long key_flags, weaksmptr(MenuBarItem) menubar_item)
 
335
{
 
336
    if(m_MenuIsActive)
 
337
    {
 
338
        if(m_CurrentMenu->area->IsMouseInside())
 
339
        {
 
340
            if(m_IsOpeningMenu == false)
 
341
            {
 
342
                // close the MenuPage that is Open
 
343
                if(m_CurrentMenu.IsValid())
 
344
                    m_CurrentMenu->menu->StopMenu(0, 0);
 
345
                m_MenuIsActive = false;
 
346
                m_CurrentMenu = smptr(MenuBarItem)(0);
 
347
            }
 
348
            else
 
349
            {
 
350
                // The MousePress before this MouseRelease, caused the MenuPage to open.
 
351
                // Set m_IsOpeningMenu so the next mouse release will close the menu.
 
352
                m_IsOpeningMenu = false;
 
353
            }
 
354
        }
 
355
        else
 
356
        {
 
357
            bool hit_inside_a_menu = false;
 
358
            bool b = m_CurrentMenu->menu->TestMouseUp(x, y, button_flags, key_flags, hit_inside_a_menu);
 
359
            if(b || (hit_inside_a_menu == false))
 
360
            {
 
361
                RecvSigTerminateMenuCascade();
 
362
            }
 
363
        }
 
364
    }
 
365
    NeedRedraw();
 
366
}
 
367
 
 
368
void MenuBar::RecvItemMouseDrag(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags, weaksmptr(MenuBarItem) menubar_item)
 
369
{
 
370
    // Transition between one menu bar item to another
 
371
    if(GetThreadWindowCompositor().GetMouseFocusArea() == menubar_item->area)
 
372
    {
 
373
        if(!menubar_item->area->IsMouseInside())  // can also test GetThreadWindowCompositor().GetMouseOverArea() != &menubar_item->area
 
374
        {
 
375
            &menubar_item->area;
 
376
            std::list< smptr(MenuBarItem) >::iterator it;
 
377
            // compute window coordinates x and y;
 
378
            int winx = menubar_item->area->GetBaseX() + x; 
 
379
            int winy = menubar_item->area->GetBaseY() + y;
 
380
            for(it = m_MenuBarItemList.begin(); it != m_MenuBarItemList.end(); it++)
 
381
            {
 
382
                smptr(CoreArea) area = (*it)->area;
 
383
                Geometry geometry = area->GetGeometry();
 
384
                if(geometry.IsPointInside(winx, winy))
 
385
                {
 
386
                    // Close the menu below menubar_item (the one that has the focus
 
387
                    menubar_item->area->ForceStopFocus(0, 0);
 
388
 
 
389
                    // EmitItemMouseEnter is going to open the menu below (*it)
 
390
                    {
 
391
                        EmitItemMouseEnter(winx, winy, button_flags, key_flags, (*it));
 
392
                        m_IsOpeningMenu = true;
 
393
                        area->ForceStartFocus(0, 0);
 
394
 
 
395
                        GetThreadWindowCompositor().SetMouseFocusArea(area);
 
396
                        GetThreadWindowCompositor().SetMouseOverArea(area);
 
397
                    }
 
398
                    
 
399
                    break;
 
400
                }
 
401
            }
 
402
        }
 
403
    }
 
404
}
 
405
 
 
406
void MenuBar::RecvSigActionTriggered(smptr(MenuPage) menu, const smptr(ActionItem) action)
 
407
{
 
408
    m_MenuIsActive = false;
 
409
    if(m_CurrentMenu.IsValid())
 
410
    {
 
411
        m_CurrentMenu->menu->StopMenu();
 
412
        NeedRedraw();
 
413
    }
 
414
    m_CurrentMenu = smptr(MenuBarItem)(0);
 
415
    m_IsOpeningMenu = false;
 
416
 
 
417
    // You can do something if you want with the menu* and the action*
 
418
}
 
419
 
 
420
 
 
421
void MenuBar::RecvSigTerminateMenuCascade()
 
422
{
 
423
    m_MenuIsActive = false;
 
424
    if(m_CurrentMenu.IsValid())
 
425
    {
 
426
        m_CurrentMenu->menu->StopMenu();
 
427
    }
 
428
    m_CurrentMenu = smptr(MenuBarItem)(0);
 
429
    m_IsOpeningMenu = false;
 
430
 
 
431
    NeedRedraw();
 
432
}
 
433
 
 
434
void MenuBar::RecvSigMouseDownOutsideMenuCascade(smptr(MenuPage) menu, int x, int y)
 
435
{
 
436
    Geometry geometry;
 
437
    std::list< smptr(MenuBarItem) >::iterator it;
 
438
    UBOOL TerminateMenuCascade = 1;
 
439
    for(it = m_MenuBarItemList.begin(); it != m_MenuBarItemList.end(); it++)
 
440
    {
 
441
        smptr(CoreArea) area = (*it)->area;
 
442
        geometry = area->GetGeometry();
 
443
        if(geometry.IsPointInside(x, y))
 
444
        {
 
445
            // The event landed on one of the MenuBar item.
 
446
            // Do nothing. This will be handled in the ProcessEvent of the MenuBar item where the mouse down landed.
 
447
            TerminateMenuCascade = 0;
 
448
            break;
 
449
        }
 
450
    }
 
451
    if(TerminateMenuCascade)
 
452
        RecvSigTerminateMenuCascade();
 
453
}
 
454
 
 
455
 
 
456
NAMESPACE_END_GUI