libyui-mga-ncurses  1.1.0
NCMGAPopupMenu.cc
1 /*
2  Copyright 2020 by Angelo Naselli <anaselli at linux dot it>
3 
4  This library is free software; you can redistribute it and/or modify
5  it under the terms of the GNU Lesser General Public License as
6  published by the Free Software Foundation; either version 2.1 of the
7  License, or (at your option) version 3.0 of the License. This library
8  is distributed in the hope that it will be useful, but WITHOUT ANY
9  WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
11  License for more details. You should have received a copy of the GNU
12  Lesser General Public License along with this library; if not, write
13  to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
14  Floor, Boston, MA 02110-1301 USA
15 
16 */
17 
18 
19 /*-/
20 
21  File: NCMGAPopupMenu.cc
22 
23  Author: Angelo Naselli <anaselli@linux.it>
24 
25 /-*/
26 
27 #define YUILogComponent "mga-ncurses"
28 #include <yui/YUILog.h>
29 #include "NCMGAPopupMenu.h"
30 #include "YMGAMenuItem.h"
31 #include "NCMenu.h"
32 #include <yui/ncurses/NCTable.h>
33 
35 {
36  NCMenu *menu;
37  unsigned maxlen;
38  wpos pos;
39  bool selected;
40 
41  //std::vector<YMGAMenuItem *> items;
42  std::map<YMGAMenuItem *, YMGAMenuItem *> itemsMap;
43 };
44 
45 
46 NCMGAPopupMenu::NCMGAPopupMenu( const wpos & at, YItemIterator begin, YItemIterator end )
47  : NCPopup( at )
48  , d(new Private)
49 {
50  YUI_CHECK_NEW ( d );
51 
52 
53 
54  std::vector<std::string> row( 2 );
55 
56  d->menu = new NCMenu( this );
57  d->maxlen = 0;
58  d->pos = at;
59  d->selected = false;
60  //d->menu->setNotify(true);
61 
62  yuiDebug() << "Menu position: " << at << std::endl;
63 
64  defsze = wsze(1, 1);
65  for ( YItemIterator it = begin; it != end; ++it )
66  {
67  YMenuSeparator *separator = dynamic_cast<YMenuSeparator *>( *it );
68  if (separator)
69  {
70  YMenuSeparator * sep = new YMenuSeparator(NULL);
71  d->menu->addItem( sep );
72  defsze.H = defsze.H > 9 ? 10 : defsze.H + 1;
73  }
74  else
75  {
76  YMGAMenuItem * item = dynamic_cast<YMGAMenuItem *>( *it );
77  YUI_CHECK_PTR( item );
78 
79  std::string label = item->hasChildren() ? item->label() + " ..." : item->label();
80  YMGAMenuItem *menuItem = new YMGAMenuItem ( label, item->iconName() );
81  menuItem->enable(item->enabled());
82  menuItem->hide(item->hidden());
83 
84  d->menu->addItem( menuItem );
85  d->itemsMap[menuItem] = item;
86 
87  if (d->maxlen < label.length()+1)
88  d->maxlen = label.length()+1;
89  // let's assume to have a menu enable scrolling for more than 10 lines
90  int h = defsze.H > 9 ? 10 : defsze.H + 1;
91  // let's assume to have a menu enable scrolling for more than 40 columns
92  int w = d->maxlen > 40 ? 40 : d->maxlen;
93 
94  defsze = wsze( h, w );
95  yuiDebug() << "Add Item: " << item->label() << " len: "<< label.length() << " HxW "<< h << "x" << w << std::endl;
96  }
97  }
98  yuiDebug() << "defsze: " << defsze << "line length: " << d->maxlen << std::endl;
99 
100  //d->menu->stripHotkeys();
101 }
102 
103 
104 NCMGAPopupMenu::~NCMGAPopupMenu()
105 {
106  d->itemsMap.clear();
107  delete d;
108 }
109 
110 int NCMGAPopupMenu::preferredHeight()
111 {
112  return defsze.H + 2; // border + scroll
113 }
114 
115 int NCMGAPopupMenu::preferredWidth()
116 {
117  return defsze.W + 2; // border + scroll
118 }
119 
120 
121 bool NCMGAPopupMenu::HasHotkey(int key)
122 {
123  yuiDebug() << key << std::endl;
124 
125  return d->menu->HasHotkey(key);
126 }
127 
128 NCursesEvent NCMGAPopupMenu::wHandleHotkey( wint_t key )
129 {
130  yuiDebug() << "Key: " << key << std::endl;
131  if ( key >= 0 && key < UCHAR_MAX ) // < myPad()->setItemByKey( key ) )
132  {
133  NCursesEvent ev = d->menu->wHandleHotkey(key);
134  yuiDebug() << "event: " << ev << std::endl;
135  if (ev != NCursesEvent::none)
136  return wHandleInput( KEY_SPACE );
137  }
138  return NCursesEvent::none;
139 }
140 
141 
142 NCursesEvent NCMGAPopupMenu::wHandleInput( wint_t ch )
143 {
144  NCursesEvent ret;
145  d->selected = false;
146 
147  yuiDebug() << "ch: " << int(ch) << std::endl;
148  switch ( ch )
149  {
150  case KEY_RIGHT:
151  {
152  YMGAMenuItem * selitem = dynamic_cast<YMGAMenuItem *>(d->menu->currentItem());
153  if (selitem)
154  {
155  YMGAMenuItem * item = d->itemsMap[ selitem ];
156  if (item->hasChildren() )
157  {
158  ret = NCursesEvent::button;
159  d->selected = true;
160  }
161  }
162  }
163  break;
164  case 0x20: //Space
165  case 0x0A: //Return
166  ret = NCursesEvent::button;
167  d->selected = true;
168  break;
169  case KEY_LEFT:
170  ret = NCursesEvent::cancel;
171  ret.detail = NCursesEvent::CONTINUE;
172  break;
173 
174  default:
175  ret = NCPopup::wHandleInput( ch );
176  break;
177  }
178 
179  return ret;
180 }
181 
182 
183 bool NCMGAPopupMenu::postAgain()
184 {
185  // dont mess up postevent.detail here
186  bool again = false;
187 
188  if (d->selected)
189  {
190  YMGAMenuItem * selected = dynamic_cast<YMGAMenuItem *>(d->menu->currentItem());
191 
192  if ( !selected )
193  {
194  d->selected = false;
195  return false;
196  }
197 
198  YMGAMenuItem * item = d->itemsMap[ selected ];
199  yuiMilestone() << "Menu item: " << item->label() << " " << item->index() << std::endl;
200 
201  if ( item->hasChildren() )
202  {
203  // post submenu
204  wpos at( ScreenPos() + wpos( selected->index(), inparent.Sze.W - 1 ) );
205  yuiDebug() << "Submenu " << item->label() << " position: " << at << std::endl;
206 
207  NCMGAPopupMenu * dialog = new NCMGAPopupMenu( at,
208  item->childrenBegin(),
209  item->childrenEnd() );
210  YUI_CHECK_NEW( dialog );
211 
212  again = ( dialog->post( &postevent ) == NCursesEvent::CONTINUE );
213  // dialog has been closed but ask the menu father to contine eventually, so let's delete it
214  YDialog::deleteTopmostDialog();
215  }
216  else
217  {
218  // store selection
219  postevent.detail = item->index();
220  again = false;
221  }
222  }
223 
224  return again;
225 }
226 
NCMenu
Definition: NCMenu.h:42
NCMGAPopupMenu::Private
Definition: NCMGAPopupMenu.cc:35
NCMGAPopupMenu
Definition: NCMGAPopupMenu.h:37