Advanced Strategic Command
selectionwindow.cpp
Go to the documentation of this file.
1 /*
2  This file is part of Advanced Strategic Command; http://www.asc-hq.de
3  Copyright (C) 1994-2010 Martin Bickel and Marc Schellenberger
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; see the file COPYING. If not, write to the
17  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  Boston, MA 02111-1307 USA
19 */
20 
21 #include "sigc++/retype_return.h"
22 #include "selectionwindow.h"
23 #include "../paradialog.h"
24 
25 bool SelectionWidget::eventMouseButtonUp (const SDL_MouseButtonEvent *button)
26 {
27  if ( button->type == SDL_MOUSEBUTTONUP && button->button == SDL_BUTTON_LEFT ) {
28  itemSelected( this );
29  return true;
30  }
31  return false;
32 };
33 
34 bool SelectionWidget::eventMouseButtonDown (const SDL_MouseButtonEvent *button)
35 {
36  if ( button->type == SDL_MOUSEBUTTONDOWN && button->button == SDL_BUTTON_LEFT ) {
37  itemMarked( this );
38  Update();
39  return true;
40  }
41  return false;
42 };
43 
44 void SelectionWidget::eventBlit ( SDL_Surface * surface, const PG_Rect & src, const PG_Rect & dst )
45 {
46  if ( selectionCallBack && selectionCallBack->operator()(this) )
47  SDL_FillRect( PG_Application::GetScreen(), const_cast<PG_Rect*>(&dst), 0xff888888 );
48 
49  display( PG_Application::GetScreen(), src, dst );
50 };
51 
52 
53 
55 {
56  WidgetList::iterator i;
57  if ( !selectedItem ) {
58  i = widgets.begin();
59  } else {
60  i = find( widgets.begin(), widgets.end(), selectedItem );
61  if ( i != widgets.end() ) {
62  if ( amount > 0 ) {
63  if ( widgets.end() - i > amount )
64  i += amount;
65  else
66  i = widgets.end() - 1;
67  } else
68  if ( amount < 0 ) {
69  if ( i - widgets.begin() >= -amount )
70  i += amount;
71  else
72  i = widgets.begin();
73  }
74  }
75  }
76 
77  if ( i == widgets.end() )
78  return false;
79 
80  if ( *i != selectedItem ) {
81  selectedItem = *i;
83  scrollWidget->ScrollToWidget( *i );
84  Update();
85  return true;
86  }
87  return false;
88 }
89 
90 bool ItemSelectorWidget::eventKeyDown(const SDL_KeyboardEvent* key)
91 {
92  if ( key->keysym.sym == SDLK_BACKSPACE ) {
93  nameSearch->SendBackspace();
94  /*
95  ASCString s = nameSearch->GetText();
96  if ( s.length() > 0 ) {
97  s.erase( s.length() - 1 );
98  nameSearch->SetText( s );
99  }
100  */
101  return true;
102  }
103  if ( key->keysym.sym == SDLK_RIGHT ) {
104  moveSelection(1);
105  return true;
106  }
107  if ( key->keysym.sym == SDLK_LEFT ) {
108  moveSelection(-1);
109  return true;
110  }
111  if ( key->keysym.sym == SDLK_UP ) {
112  moveSelection(-columnCount);
113  return true;
114  }
115  if ( key->keysym.sym == SDLK_DOWN ) {
116  moveSelection(columnCount);
117  return true;
118  }
119  if ( key->keysym.sym == SDLK_HOME ) {
120  moveSelection(-int(widgets.size()) );
121  return true;
122  }
123  if ( key->keysym.sym == SDLK_END ) {
124  moveSelection(widgets.size());
125  return true;
126  }
127  if ( key->keysym.sym == SDLK_PAGEUP ) {
128  moveSelection( -columnCount * visibleRowCount );
129  return true;
130  }
131  if ( key->keysym.sym == SDLK_PAGEDOWN ) {
132  moveSelection(columnCount * visibleRowCount);
133  return true;
134  }
135 
136  if ( key->keysym.sym == SDLK_RETURN || key->keysym.sym == SDLK_KP_ENTER) {
137  if ( namesConstrained ) {
138  if ( selectedItem && (nameMatch( selectedItem, nameSearch->GetText()) || nameSearch->GetText().length() == 0) ) {
139  itemSelected( selectedItem, false );
140  return true;
141  }
142  } else {
143  if ( nameSearch->GetText().length() ) {
144  nameEntered( nameSearch->GetText() );
145  return true;
146  } else {
147  if ( selectedItem ) {
148  itemSelected( selectedItem, false );
149  return true;
150  }
151  }
152  }
153  }
154 
155 
156 
157  if ( key->keysym.unicode <= 255 && key->keysym.unicode >= 0x20 ) {
158  ASCString newtext = nameSearch->GetText() + char ( key->keysym.unicode );
159  if ( locateObject( newtext ) || !namesConstrained )
160  nameSearch->SendChar( key->keysym.unicode );
161 
162  return true;
163  }
164 
165  return false;
166 };
167 
169 {
170  Update();
171  factory->itemSelected( w, mouse );
172  sigItemSelected( w );
173 }
174 
176 {
177  selectedItem = w;
178  factory->itemMarked( w );
179 }
180 
181 
183 {
184  return w == selectedItem;
185 }
186 
188 {
189  for ( WidgetList::iterator i = widgets.begin(); i != widgets.end(); ++i ) {
190  if ( nameMatch( *i, name ) ) {
191  markItem( *i );
192  scrollWidget->ScrollToWidget( *i );
193  Update();
194  return true;
195  }
196  }
197  return false;
198 }
199 
201 {
202  ASCString a = name;
203  a.toLower();
204  ASCString b = selection->getName().toLower();
205  if ( a.length() > 0 && b.length() > 0 )
206  if ( b.find ( a ) == 0 )
207  return true;
208  return false;
209 };
210 
211 
212 class NonEditableLineEdit : public PG_LineEdit {
213  public:
214  NonEditableLineEdit (PG_Widget *parent, const PG_Rect &r=PG_Rect::null, const std::string &style="LineEdit", int maximumLength=1000000) : PG_LineEdit( parent, r, style, maximumLength)
215  {
216  EditBegin();
217  SetTransparency(255);
218  SetBorderSize(0);
219  };
220  virtual bool eventKeyDown (const SDL_KeyboardEvent *key) { return false; };
221  virtual bool eventFilterKey (const SDL_KeyboardEvent *key) { return true; };
222 
223 };
224 
225 ItemSelectorWidget::ItemSelectorWidget( PG_Widget *parent, const PG_Rect &r , SelectionItemFactory* itemFactory )
226  : PG_Widget( parent,r ), namesConstrained(true), rowCount(0), scrollWidget( NULL), nameSearch(NULL), selectedItem(NULL), factory( itemFactory ), columnCount(-1), visibleRowCount(-1), selectionCallBack( this, &ItemSelectorWidget::isItemMarked ) {
227  SetTransparency(255);
228  reLoad();
229 
230  markItem( itemFactory->getDefaultItem() );
231  int bottom = 0; // itemFactory->getBottomLineHeight();
232  Emboss* e = new Emboss( this, PG_Rect( 1, Height() - 26 - bottom, Width()-20, 22), true );
233  nameSearch = new NonEditableLineEdit ( e, PG_Rect( 4,1, e->Width()-4 , e->Height()-2 ));
234 
235  // factory->spawnBottonWidgets( this, PG_Rect( 1, Height() - bottom, Width()-20, bottom-1));
236  // nameSearch = new PG_Label ( this, PG_Rect( 5, Height() - 25, Width() - 10, 20 ));
237 };
238 
239 
241 {
242  namesConstrained = constrain;
243 }
244 
245 void ItemSelectorWidget::reLoad( bool show )
246 {
247  int orgx = -1;
248  int orgy = -1;
249  if ( scrollWidget ) {
250  orgx = scrollWidget->GetScrollPosX();
251  orgy = scrollWidget->GetScrollPosY();
252  }
253  delete scrollWidget;
254  scrollWidget = new PG_ScrollWidget( this , PG_Rect( 0, 0, Width(), Height() - 30 ));
255  scrollWidget->SetTransparency(255);
256  widgets.clear();
257 
258  int x = 0;
259  int y = 0;
260 
261  factory->restart();
262  SelectionWidget* w;
263  while ( (w = factory->spawnNextItem( scrollWidget, PG_Point(x,y))) ) {
264 
265  if ( columnCount < 0 )
266  columnCount = scrollWidget->Width() / (w->Width() + w->gap());
267 
268  if ( visibleRowCount < 0 )
269  visibleRowCount = scrollWidget->Height() / (w->Height() + w->gap());
270 
271  w->itemSelected.connect( sigc::bind( sigc::mem_fun( *this, &ItemSelectorWidget::itemSelected ), true ));
272  w->itemMarked.connect( sigc::mem_fun( *this, &ItemSelectorWidget::markItem ));
273  w->setSelectionCallback( &selectionCallBack );
274  widgets.push_back ( w );
275 
276  x += w->Width() + w->gap();
277  if ( x + w->Width() + w->gap() >= scrollWidget->Width() ) {
278  x = 0;
279  y += w->Height() + w->gap();
280  }
281  }
282 
283  if ( orgx >= 0 && orgy >= 0 )
284  scrollWidget->ScrollTo ( orgx, orgy );
285 
286  if ( show )
287  // scrollWidget->Update();
288  scrollWidget->Show();
289 }
290 
291 
293 {
294  nameSearch->SetText( "" );
295 }
296 
298 {
299  delete factory;
300 }
301 
302 
303 
304 ItemSelectorWindow::ItemSelectorWindow( PG_Widget *parent, const PG_Rect &r , const ASCString& title, SelectionItemFactory* itemFactory )
305  : ASC_PG_Dialog( parent,r, title)
306 {
307  SetTransparency( 0 );
308 
309  itemSelector = new ItemSelectorWidget( this, PG_Rect( 5, GetTitlebarHeight () + 2, Width()-5, Height()- GetTitlebarHeight ()- 5 ), itemFactory );
310 
311  itemSelector->sigItemSelected.connect( sigc::mem_fun( *this, &ItemSelectorWindow::itemSelected ));
312  itemSelector->sigQuitModal.connect( sigc::mem_fun( *this, &ItemSelectorWindow::QuitModal));
313 };
314 
315 void ItemSelectorWindow::itemSelected( const SelectionWidget* )
316 {
317  Hide();
318  QuitModal();
319 }
320 
321 bool ItemSelectorWindow::eventKeyDown(const SDL_KeyboardEvent* key)
322 {
323  if ( key->keysym.sym == SDLK_ESCAPE ) {
324  QuitModal();
325  return true;
326  }
327  return false;
328 }
329 
331 {
332  itemSelector ->resetNamesearch();
333  return PG_Window::RunModal();
334 }
335 
337 {
338  itemSelector->reLoad();
339 }
virtual SelectionWidget * getDefaultItem()
void reLoad(bool show=false)
bool eventMouseButtonUp(const SDL_MouseButtonEvent *button)
bool nameMatch(const SelectionWidget *selection, const ASCString &name)
void itemSelected(const SelectionWidget *w, bool mouse)
ASCString & toLower()
Definition: ascstring.cpp:36
virtual void restart()=0
void eventBlit(SDL_Surface *surface, const PG_Rect &src, const PG_Rect &dst)
virtual bool eventFilterKey(const SDL_KeyboardEvent *key)
sigc::signal< void, const SelectionWidget * > sigItemSelected
bool eventKeyDown(const SDL_KeyboardEvent *key)
sigc::signal< bool > sigQuitModal
virtual ASCString getName() const =0
bool isItemMarked(const SelectionWidget *w)
bool eventKeyDown(const SDL_KeyboardEvent *key)
virtual void itemMarked(const SelectionWidget *widget)
sigc::signal< void, ASCString > nameEntered
bool moveSelection(int amount)
The ASCString class provides an abstract way to manipulate strings.
Definition: ascstring.h:14
ItemSelectorWidget(PG_Widget *parent, const PG_Rect &r, SelectionItemFactory *itemFactory)
void constrainNames(bool constrain)
virtual SelectionWidget * spawnNextItem(PG_Widget *parent, const PG_Point &pos)=0
bool locateObject(const ASCString &name)
NonEditableLineEdit(PG_Widget *parent, const PG_Rect &r=PG_Rect::null, const std::string &style="LineEdit", int maximumLength=1000000)
virtual int gap()
virtual void itemSelected(const SelectionWidget *widget, bool mouse)=0
Adapter class for using Paragui Dialogs in ASC. This class transfers the event control from ASC to Pa...
Definition: paradialog.h:127
virtual bool eventKeyDown(const SDL_KeyboardEvent *key)
SelectionHolder selection
Definition: edglobal.cpp:189
void setSelectionCallback(SelectionCallBack *callBack)
ItemSelectorWindow(PG_Widget *parent, const PG_Rect &r, const ASCString &title, SelectionItemFactory *itemFactory)
bool eventMouseButtonDown(const SDL_MouseButtonEvent *button)
sigc::signal< void, const SelectionWidget * > itemSelected
sigc::signal< void, const SelectionWidget * > itemMarked
void markItem(const SelectionWidget *w)
virtual void display(SDL_Surface *surface, const PG_Rect &src, const PG_Rect &dst)=0