~ubuntu-branches/debian/sid/stella/sid

« back to all changes in this revision

Viewing changes to src/gui/Dialog.cxx

  • Committer: Package Import Robot
  • Author(s): Stephen Kitt
  • Date: 2013-06-28 09:53:13 UTC
  • mfrom: (1.3.6)
  • Revision ID: package-import@ubuntu.com-20130628095313-j8jkkgxpvx1t18ym
Tags: 3.9-1
New upstream version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
// See the file "License.txt" for information on usage and redistribution of
15
15
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
16
16
//
17
 
// $Id: Dialog.cxx 2579 2013-01-04 19:49:01Z stephena $
 
17
// $Id: Dialog.cxx 2747 2013-06-17 15:57:41Z stephena $
18
18
//
19
19
//   Based on code from ScummVM - Scumm Interpreter
20
20
//   Copyright (C) 2002-2004 The ScummVM project
46
46
    _cancelWidget(0),
47
47
    _visible(false),
48
48
    _isBase(isBase),
49
 
    _ourTab(NULL),
50
 
    _surface(NULL),
51
 
    _focusID(0),
52
 
    _surfaceID(-1)
 
49
    _processCancel(false),
 
50
    _surface(0),
 
51
    _tabID(0)
53
52
{
54
53
}
55
54
 
56
55
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
57
56
Dialog::~Dialog()
58
57
{
59
 
  for(unsigned int i = 0; i < _ourFocusList.size(); ++i)
60
 
    _ourFocusList[i].focusList.clear();
 
58
  _myFocus.list.clear();
 
59
  _myTabList.clear();
61
60
 
62
61
  delete _firstWidget;
63
62
  _firstWidget = NULL;
64
63
 
65
 
  _ourButtonGroup.clear();
 
64
  _buttonGroup.clear();
66
65
}
67
66
 
68
67
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
69
 
void Dialog::open()
 
68
void Dialog::open(bool refresh)
70
69
{
71
 
  _result = 0;
72
 
  _visible = true;
73
 
 
74
70
  // Make sure we have a valid surface to draw into
75
71
  // Technically, this shouldn't be needed until drawDialog(), but some
76
72
  // dialogs cause drawing to occur within loadConfig()
80
76
  // However, this policy is left entirely to the framebuffer
81
77
  // We suggest the hint here, but specific framebuffers are free to
82
78
  // ignore it
83
 
  _surface = instance().frameBuffer().surface(_surfaceID);
84
79
  if(_surface == NULL)
85
80
  {
86
 
    _surfaceID = instance().frameBuffer().allocateSurface(_w, _h, _isBase);
87
 
    _surface   = instance().frameBuffer().surface(_surfaceID);
 
81
    uInt32 surfaceID = instance().frameBuffer().allocateSurface(_w, _h, _isBase);
 
82
    _surface = instance().frameBuffer().surface(surfaceID);
88
83
  }
 
84
  parent().addDialog(this);
89
85
 
90
86
  center();
91
87
  loadConfig();
92
88
 
93
89
  // (Re)-build the focus list to use for the widgets which are currently
94
90
  // onscreen
95
 
  buildFocusWidgetList(_focusID);
 
91
  buildCurrentFocusList();
 
92
 
 
93
  _visible = true;
 
94
 
 
95
  if(refresh)
 
96
    instance().frameBuffer().refresh();
96
97
}
97
98
 
98
99
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
99
 
void Dialog::close()
 
100
void Dialog::close(bool refresh)
100
101
{
101
102
  if (_mouseWidget)
102
103
  {
105
106
  }
106
107
 
107
108
  releaseFocus();
 
109
 
 
110
  _visible = false;
 
111
 
108
112
  parent().removeDialog();
109
113
 
110
 
  _visible = false;
 
114
  if(refresh)
 
115
    instance().frameBuffer().refresh();
111
116
}
112
117
 
113
118
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
135
140
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
136
141
void Dialog::addFocusWidget(Widget* w)
137
142
{
138
 
  // All focusable widgets should retain focus
139
 
  if(w)
140
 
    w->setFlags(WIDGET_RETAIN_FOCUS);
141
 
 
142
 
  if(_ourFocusList.size() == 0)
 
143
  if(!w)
 
144
    return;
 
145
 
 
146
  // All focusable widgets should retain focus
 
147
  w->setFlags(WIDGET_RETAIN_FOCUS);
 
148
 
 
149
  _myFocus.widget = w;
 
150
  _myFocus.list.push_back(w);
 
151
}
 
152
 
 
153
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
154
void Dialog::addToFocusList(WidgetArray& list)
 
155
{
 
156
  // All focusable widgets should retain focus
 
157
  for(uInt32 i = 0; i < list.size(); ++i)
 
158
    list[i]->setFlags(WIDGET_RETAIN_FOCUS);
 
159
 
 
160
  _myFocus.list.push_back(list);
 
161
  _focusList = _myFocus.list;
 
162
 
 
163
  if(list.size() > 0)
 
164
    _myFocus.widget = list[0];
 
165
}
 
166
 
 
167
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
168
void Dialog::addToFocusList(WidgetArray& list, TabWidget* w, int tabId)
 
169
{
 
170
  // Only add the list if the tab actually exists
 
171
  if(!w || w->getID() < 0 || (uInt32)w->getID() >= _myTabList.size())
 
172
    return;
 
173
 
 
174
  assert(w == _myTabList[w->getID()].widget);
 
175
 
 
176
  // All focusable widgets should retain focus
 
177
  for(uInt32 i = 0; i < list.size(); ++i)
 
178
    list[i]->setFlags(WIDGET_RETAIN_FOCUS);
 
179
 
 
180
  // First get the appropriate focus list
 
181
  FocusList& focus = _myTabList[w->getID()].focus;
 
182
 
 
183
  // Now insert in the correct place in that focus list
 
184
  uInt32 id = tabId;
 
185
  if(id < focus.size())
 
186
    focus[id].list.push_back(list);
 
187
  else
143
188
  {
144
 
        Focus f;
145
 
    f.focusedWidget = 0;
146
 
        _ourFocusList.push_back(f);
 
189
    // Make sure the array is large enough
 
190
    while(focus.size() <= id)
 
191
      focus.push_back(Focus());
 
192
 
 
193
    focus[id].list.push_back(list);
147
194
  }
148
 
  _ourFocusList[0].focusedWidget = w;
149
 
  _ourFocusList[0].focusList.push_back(w);
 
195
 
 
196
  if(list.size() > 0)
 
197
    focus[id].widget = list[0];
150
198
}
151
199
 
152
200
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
153
 
void Dialog::addToFocusList(WidgetArray& list, int id)
 
201
void Dialog::addTabWidget(TabWidget* w)
154
202
{
155
 
  // All focusable widgets should retain focus
156
 
  for(unsigned int i = 0; i < list.size(); ++i)
157
 
    list[i]->setFlags(WIDGET_RETAIN_FOCUS);
158
 
 
159
 
  id++;  // Arrays start at 0, not -1.
 
203
  if(!w || w->getID() < 0)
 
204
    return;
160
205
 
161
206
  // Make sure the array is large enough
162
 
  while((int)_ourFocusList.size() <= id)
163
 
  {
164
 
    Focus f;
165
 
    f.focusedWidget = NULL;
166
 
    _ourFocusList.push_back(f);
167
 
  }
168
 
 
169
 
  _ourFocusList[id].focusList.push_back(list);
170
 
  if(id == 0 && _ourFocusList.size() > 0)
171
 
    _focusList = _ourFocusList[0].focusList;
172
 
 
173
 
  if(list.size() > 0)
174
 
    _ourFocusList[id].focusedWidget = list[0];
 
207
  uInt32 id = w->getID();
 
208
  while(_myTabList.size() < id)
 
209
    _myTabList.push_back(TabFocus());
 
210
 
 
211
  _myTabList.push_back(TabFocus(w));
175
212
}
176
213
 
177
214
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
183
220
  {
184
221
    // Redraw widgets for new focus
185
222
    _focusedWidget = Widget::setFocusForChain(this, getFocusList(), w, 0);
 
223
 
 
224
    // Update current tab based on new focused widget
 
225
    getTabIdForWidget(_focusedWidget);
186
226
  }
187
227
}
188
228
 
189
229
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
190
 
void Dialog::buildFocusWidgetList(int id)
 
230
void Dialog::buildCurrentFocusList(int tabID)
191
231
{
192
232
  // Yes, this is hideously complex.  That's the price we pay for
193
233
  // tab navigation ...
194
 
 
195
 
  // Remember which item previously had focus, but only if it belongs
196
 
  // to this focus list
197
 
  if(_focusID < (int)_ourFocusList.size() &&
198
 
     Widget::isWidgetInChain(_ourFocusList[_focusID].focusList, _focusedWidget))
199
 
    _ourFocusList[_focusID].focusedWidget = _focusedWidget;
200
 
 
201
 
  _focusID = id;
202
 
 
203
 
  // Create a focuslist for items currently onscreen
204
 
  // We do this by starting with any dialog focus list (at index 0 in the
205
 
  // focus lists, then appending the list indicated by 'id'.
206
 
  if(_focusID < (int)_ourFocusList.size())
 
234
  _focusList.clear();
 
235
 
 
236
  // Remember which tab item previously had focus, if applicable
 
237
  // This only applies if this method was called for a tab change
 
238
  Widget* tabFocusWidget = 0;
 
239
  if(tabID >= 0 && tabID < (int)_myTabList.size())
207
240
  {
208
 
    _focusList.clear();
209
 
    _focusList.push_back(_ourFocusList[0].focusList);
210
 
 
211
 
    // Append extra focus list
212
 
    if(_focusID > 0)
213
 
      _focusList.push_back(_ourFocusList[_focusID].focusList);
214
 
 
215
 
    // Add button group at end of current focus list
216
 
    // We do it this way for TabWidget, so that buttons are scanned
217
 
    // *after* the widgets in the current tab
218
 
    if(_ourButtonGroup.size() > 0)
219
 
      _focusList.push_back(_ourButtonGroup);
220
 
 
221
 
    // Only update _focusedWidget if it doesn't belong to the main focus list
222
 
    // HACK - figure out how to properly deal with only one focus-able widget
223
 
    // in a tab -- TabWidget is the spawn of the devil
224
 
    if(_focusList.size() == 1)
225
 
      _focusedWidget = _focusList[0];
226
 
    else if(!Widget::isWidgetInChain(_ourFocusList[0].focusList, _focusedWidget))
227
 
      _focusedWidget = _ourFocusList[_focusID].focusedWidget;
 
241
    // Save focus in previously selected tab column,
 
242
    // and get focus for new tab column
 
243
    TabFocus& tabfocus = _myTabList[tabID];
 
244
    tabfocus.saveCurrentFocus(_focusedWidget);
 
245
    tabFocusWidget = tabfocus.getNewFocus();
 
246
 
 
247
    _tabID = tabID;
228
248
  }
229
 
  else
230
 
    _focusedWidget = 0;
 
249
 
 
250
  // Add appropriate items from tablist (if present)
 
251
  for(uInt32 id = 0; id < _myTabList.size(); ++id)
 
252
    _myTabList[id].appendFocusList(_focusList);
 
253
 
 
254
  // Add remaining items from main focus list
 
255
  _focusList.push_back(_myFocus.list);
 
256
 
 
257
  // Add button group at end of current focus list
 
258
  // We do it this way for TabWidget, so that buttons are scanned
 
259
  // *after* the widgets in the current tab
 
260
  if(_buttonGroup.size() > 0)
 
261
    _focusList.push_back(_buttonGroup);
 
262
 
 
263
  // Finally, the moment we've all been waiting for :)
 
264
  // Set the actual focus widget
 
265
  if(tabFocusWidget)
 
266
    _focusedWidget = tabFocusWidget;
 
267
  else if(!_focusedWidget && _focusList.size() > 0)
 
268
    _focusedWidget = _focusList[0];
231
269
}
232
270
 
233
271
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
295
333
  // not ascii??
296
334
  if(instance().eventHandler().kbdShift(mod))
297
335
  {
298
 
    if(key == KBDK_LEFT && _ourTab)       // left arrow
299
 
    {
300
 
      _ourTab->cycleTab(-1);
301
 
      return;
302
 
    }
303
 
    else if(key == KBDK_RIGHT && _ourTab) // right arrow
304
 
    {
305
 
      _ourTab->cycleTab(+1);
306
 
      return;
307
 
    }
308
 
    else if(key == KBDK_TAB)     // tab
 
336
    if(key == KBDK_LEFT && cycleTab(-1))
 
337
      return;
 
338
    else if(key == KBDK_RIGHT && cycleTab(+1))
 
339
      return;
 
340
    else if(key == KBDK_TAB)
309
341
      e = Event::UINavPrev;
310
342
  }
311
 
  else if(key == KBDK_TAB)       // tab
 
343
  else if(key == KBDK_TAB)
312
344
    e = Event::UINavNext;
313
345
 
314
346
  // Check the keytable now, since we might get one of the above events,
338
370
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
339
371
void Dialog::handleMouseDown(int x, int y, int button, int clickCount)
340
372
{
341
 
  Widget* w;
342
 
  w = findWidget(x, y);
 
373
  Widget* w = findWidget(x, y);
343
374
 
344
375
  _dragWidget = w;
345
 
 
346
376
  setFocus(w);
347
377
 
348
378
  if(w)
349
 
    w->handleMouseDown(x - (w->getAbsX() - _x), y - (w->getAbsY() - _y), button, clickCount);
 
379
    w->handleMouseDown(x - (w->getAbsX() - _x), y - (w->getAbsY() - _y),
 
380
                       button, clickCount);
350
381
}
351
382
 
352
383
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
353
384
void Dialog::handleMouseUp(int x, int y, int button, int clickCount)
354
385
{
355
 
  Widget* w;
356
 
 
357
386
  if(_focusedWidget)
358
387
  {
359
388
    // Lose focus on mouseup unless the widget requested to retain the focus
361
390
      releaseFocus();
362
391
  }
363
392
 
364
 
  w = _dragWidget;
365
 
 
 
393
  Widget* w = _dragWidget;
366
394
  if(w)
367
 
    w->handleMouseUp(x - (w->getAbsX() - _x), y - (w->getAbsY() - _y), button, clickCount);
 
395
    w->handleMouseUp(x - (w->getAbsX() - _x), y - (w->getAbsY() - _y),
 
396
                     button, clickCount);
368
397
 
369
398
  _dragWidget = 0;
370
399
}
372
401
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
373
402
void Dialog::handleMouseWheel(int x, int y, int direction)
374
403
{
375
 
  Widget* w;
376
 
 
377
404
  // This may look a bit backwards, but I think it makes more sense for
378
405
  // the mouse wheel to primarily affect the widget the mouse is at than
379
406
  // the widget that happens to be focused.
380
407
 
381
 
  w = findWidget(x, y);
 
408
  Widget* w = findWidget(x, y);
382
409
  if(!w)
383
410
    w = _focusedWidget;
384
 
  if (w)
 
411
  if(w)
385
412
    w->handleMouseWheel(x, y, direction);
386
413
}
387
414
 
389
416
void Dialog::handleMouseMoved(int x, int y, int button)
390
417
{
391
418
  Widget* w;
392
 
        
 
419
  
393
420
  if(_focusedWidget && !_dragWidget)
394
421
  {
395
422
    w = _focusedWidget;
396
423
    int wx = w->getAbsX() - _x;
397
424
    int wy = w->getAbsY() - _y;
398
 
                
 
425
    
399
426
    // We still send mouseEntered/Left messages to the focused item
400
427
    // (but to no other items).
401
428
    bool mouseInFocusedWidget = (x >= wx && x < wx + w->_w && y >= wy && y < wy + w->_h);
441
468
  Widget* w = findWidget(x, y);
442
469
 
443
470
  if(w)
444
 
    return w->handleMouseClicks(x - (w->getAbsX() - _x), y - (w->getAbsY() - _y), button);
 
471
    return w->handleMouseClicks(x - (w->getAbsX() - _x),
 
472
                                y - (w->getAbsY() - _y), button);
445
473
  else
446
474
    return false;
447
475
}
516
544
      {
517
545
        _focusedWidget = Widget::setFocusForChain(this, getFocusList(),
518
546
                                                  _focusedWidget, -1);
 
547
        // Update current tab based on new focused widget
 
548
        getTabIdForWidget(_focusedWidget);
 
549
 
519
550
        return true;
520
551
      }
521
552
      break;
525
556
      {
526
557
        _focusedWidget = Widget::setFocusForChain(this, getFocusList(),
527
558
                                                  _focusedWidget, +1);
 
559
        // Update current tab based on new focused widget
 
560
        getTabIdForWidget(_focusedWidget);
 
561
 
528
562
        return true;
529
563
      }
530
564
      break;
545
579
        _cancelWidget->handleEvent(Event::UISelect);
546
580
        return true;
547
581
      }
 
582
      else if(_processCancel)
 
583
      {
 
584
        // Some dialogs want the ability to cancel without actually having
 
585
        // a corresponding cancel button
 
586
        close();
 
587
        return true;
 
588
      }
548
589
      break;
549
590
 
550
591
    default:
555
596
}
556
597
 
557
598
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
599
void Dialog::getTabIdForWidget(Widget* w)
 
600
{
 
601
  if(_myTabList.size() == 0 || !w)
 
602
    return;
 
603
 
 
604
  for(uInt32 id = 0; id < _myTabList.size(); ++id)
 
605
  {
 
606
    if(w->_boss == _myTabList[id].widget)
 
607
    {
 
608
      _tabID = id;
 
609
      return;
 
610
    }
 
611
  }
 
612
}
 
613
 
 
614
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
615
bool Dialog::cycleTab(int direction)
 
616
{
 
617
  if(_tabID >= 0 && _tabID < (int)_myTabList.size())
 
618
  {
 
619
    _myTabList[_tabID].widget->cycleTab(direction);
 
620
    return true;
 
621
  }
 
622
  return false;
 
623
}
 
624
 
 
625
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
558
626
void Dialog::handleCommand(CommandSender* sender, int cmd, int data, int id)
559
627
{
560
628
  switch(cmd)
561
629
  {
562
630
    case kTabChangedCmd:
563
 
      // Add this focus list for the given tab to the global focus list
564
 
      buildFocusWidgetList(++data);
 
631
      if(_visible)
 
632
        buildCurrentFocusList(id);
565
633
      break;
566
634
 
567
635
    case kCloseCmd:
580
648
  return Widget::findWidgetInChain(_firstWidget, x, y);
581
649
}
582
650
 
583
 
 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
651
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
584
652
void Dialog::addOKCancelBGroup(WidgetArray& wid, const GUI::Font& font,
585
653
                               const string& okText, const string& cancelText)
586
654
{
614
682
  addOKWidget(b);
615
683
#endif
616
684
}
 
685
 
 
686
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
687
Dialog::Focus::Focus(Widget* w)
 
688
  : widget(w)
 
689
{
 
690
}
 
691
 
 
692
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
693
Dialog::Focus::~Focus()
 
694
{
 
695
  list.clear();
 
696
}
 
697
 
 
698
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
699
Dialog::TabFocus::TabFocus(TabWidget* w)
 
700
  : widget(w),
 
701
    currentTab(0)
 
702
{
 
703
}
 
704
 
 
705
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
706
Dialog::TabFocus::~TabFocus()
 
707
{
 
708
  focus.clear();
 
709
}
 
710
 
 
711
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
712
void Dialog::TabFocus::appendFocusList(WidgetArray& list)
 
713
{
 
714
  int active = widget->getActiveTab();
 
715
 
 
716
  if(active >= 0 && active < (int)focus.size())
 
717
    list.push_back(focus[active].list);
 
718
}
 
719
 
 
720
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
721
void Dialog::TabFocus::saveCurrentFocus(Widget* w)
 
722
{
 
723
  if(currentTab < focus.size() &&
 
724
      Widget::isWidgetInChain(focus[currentTab].list, w))
 
725
    focus[currentTab].widget = w;
 
726
}
 
727
 
 
728
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
729
Widget* Dialog::TabFocus::getNewFocus()
 
730
{
 
731
  currentTab = widget->getActiveTab();
 
732
 
 
733
  return (currentTab < focus.size()) ? focus[currentTab].widget : 0;
 
734
}