libyui  3.10.0
YItemSelector.cc
1 /*
2  Copyright (c) [2019] SUSE LLC
3  This library is free software; you can redistribute it and/or modify
4  it under the terms of the GNU Lesser General Public License as
5  published by the Free Software Foundation; either version 2.1 of the
6  License, or (at your option) version 3.0 of the License. This library
7  is distributed in the hope that it will be useful, but WITHOUT ANY
8  WARRANTY; without even the implied warranty of MERCHANTABILITY or
9  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
10  License for more details. You should have received a copy of the GNU
11  Lesser General Public License along with this library; if not, write
12  to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
13  Floor, Boston, MA 02110-1301 USA
14 */
15 
16 
17 /*-/
18 
19  File: YItemSelector.cc
20 
21  Author: Stefan Hundhammer <shundhammer@suse.de>
22 
23 /-*/
24 
25 #define YUILogComponent "ui"
26 #include "YUILog.h"
27 
28 #include "YItemSelector.h"
29 
30 #define DEFAULT_VISIBLE_ITEMS 3
31 
32 using std::string;
33 
34 
36 {
38  : visibleItems( DEFAULT_VISIBLE_ITEMS )
39  {}
40 
41  int visibleItems;
42  YItemCustomStatusVector customStates;
43 };
44 
45 
47  bool enforceSingleSelection )
48  : YSelectionWidget( parent,
49  "", // label
50  enforceSingleSelection )
51  , priv( new YItemSelectorPrivate )
52 {
53  YUI_CHECK_NEW( priv );
54 
55  init();
56 }
57 
58 
60  const YItemCustomStatusVector & customStates )
61  : YSelectionWidget( parent,
62  "", // label
63  false ) // enforceSingleSelection )
64  , priv( new YItemSelectorPrivate )
65 {
66  YUI_CHECK_NEW( priv );
67 
68  priv->customStates = customStates;
69  init();
70  checkCustomStates();
71 }
72 
73 
75 {
76  // NOP
77 }
78 
79 
80 void YItemSelector::init()
81 {
83 
84  setDefaultStretchable( YD_HORIZ, true );
85  setDefaultStretchable( YD_VERT, true );
86 }
87 
88 
89 const char *
91 {
92  if ( usingCustomStatus() )
93  return "YCustomStatusItemSelector";
94 
95  return enforceSingleSelection() ? "YSingleItemSelector" : "YMultiItemSelector";
96 }
97 
98 
99 int
101 {
102  return priv->visibleItems;
103 }
104 
105 
107 {
108  if ( newVal < 1 )
109  newVal = 1;
110 
111  priv->visibleItems = newVal;
112 }
113 
114 
115 void YItemSelector::setItemStatus( YItem * item, int status )
116 {
117  if ( usingCustomStatus() )
118  {
119  YUI_CHECK_INDEX( status, -1, customStatusCount() - 1 );
120  item->setStatus( status );
122 
123  // Intentionally NOT calling the parent class implementation since that
124  // would only store 0 or 1 as the item's status.
125  }
126  else
127  {
128  // Let the parent class handle this and also take care of enforcing
129  // single selection (if configured).
130 
131  YSelectionWidget::setItemStatus( item, status );
132  }
133 }
134 
135 
137 {
138  return ! priv->customStates.empty();
139 }
140 
141 
143 {
144  return priv->customStates.size();
145 }
146 
147 
148 const YItemCustomStatus &
150 {
151  // std::vector::at() does bounds checking of 'index', possibly throwing a
152  // std::out_of_range exception.
153  //
154  // std::vector::operator[] does not do any checking and may just cause a
155  // segfault or misbehave in spectacular ways.
156 
157  return priv->customStates.at( (YItemCustomStatusVector::size_type) index );
158 }
159 
160 
162 {
163  return index >= 0 && index < customStatusCount();
164 }
165 
166 
167 void YItemSelector::checkCustomStates()
168 {
169  if ( priv->customStates.size() < 2 )
170  YUI_THROW( YUIException( "Need at least 2 different custom status value definitions" ) );
171 
172  int maxStatus = priv->customStates.size() - 1;
173 
174  for ( int i=0; i <= maxStatus; ++i )
175  {
176  YItemCustomStatus & status = priv->customStates.at( (YItemCustomStatusVector::size_type) i );
177 
178  if ( status.nextStatus() > maxStatus )
179  {
180  yuiError() << "Invalid nextStatus " << status.nextStatus()
181  << " for status #" << i
182  << endl;
183 
184  status.setNextStatus( -1 );
185  }
186  else if ( status.nextStatus() < -1 )
187  status.setNextStatus( -1 );
188  else
189  {
190  yuiDebug() << "Status #" << i << ": next status: #" << status.nextStatus() << endl;
191  }
192  }
193 }
194 
195 
197 {
198  if ( ! validCustomStatusIndex( oldStatus ) )
199  {
200  yuiDebug() << "Invalid old status: " << oldStatus << endl;
201  return oldStatus;
202  }
203  else
204  return priv->customStates.at( oldStatus ).nextStatus();
205 }
206 
207 
208 const YPropertySet &
210 {
211  static YPropertySet propSet;
212 
213  if ( propSet.isEmpty() )
214  {
215  /*
216  * @property itemID Value The (first) currently selected item
217  * @property itemID CurrentItem The (first) currently selected item
218  * @property itemList SelectedItems All currently selected items
219  * @property itemList Items All items
220  * @property statusMap ItemStatus The (numeric) status values of the items
221  * @property integer VisibleItems Number of items that are visible without scrolling
222  * @property string IconPath Base path for icons
223  */
224  propSet.add( YProperty( YUIProperty_Value, YOtherProperty ) );
225  propSet.add( YProperty( YUIProperty_CurrentItem, YOtherProperty ) );
226  propSet.add( YProperty( YUIProperty_SelectedItems, YOtherProperty ) );
227  propSet.add( YProperty( YUIProperty_Items, YOtherProperty ) );
228  propSet.add( YProperty( YUIProperty_ItemStatus, YOtherProperty ) );
229  propSet.add( YProperty( YUIProperty_VisibleItems, YIntegerProperty ) );
230  propSet.add( YProperty( YUIProperty_IconPath, YStringProperty ) );
231  propSet.add( YWidget::propertySet() );
232  }
233 
234  return propSet;
235 }
236 
237 
238 bool
239 YItemSelector::setProperty( const string & propertyName, const YPropertyValue & val )
240 {
241  propertySet().check( propertyName, val.type() ); // throws exceptions if not found or type mismatch
242 
243  if ( propertyName == YUIProperty_Value ) return false; // Needs special handling
244  else if ( propertyName == YUIProperty_CurrentItem ) return false; // Needs special handling
245  else if ( propertyName == YUIProperty_SelectedItems ) return false; // Needs special handling
246  else if ( propertyName == YUIProperty_Items ) return false; // Needs special handling
247  else if ( propertyName == YUIProperty_ItemStatus ) return false; // Needs special handling
248  else if ( propertyName == YUIProperty_VisibleItems ) setVisibleItems( val.integerVal() );
249  else if ( propertyName == YUIProperty_IconPath ) setIconBasePath( val.stringVal() );
250  else
251  {
252  return YWidget::setProperty( propertyName, val );
253  }
254 
255  return true; // success -- no special processing necessary
256 }
257 
258 
260 YItemSelector::getProperty( const string & propertyName )
261 {
262  propertySet().check( propertyName ); // throws exceptions if not found
263 
264  if ( propertyName == YUIProperty_Value ) return YPropertyValue( YOtherProperty );
265  else if ( propertyName == YUIProperty_CurrentItem ) return YPropertyValue( YOtherProperty );
266  else if ( propertyName == YUIProperty_SelectedItems ) return YPropertyValue( YOtherProperty );
267  else if ( propertyName == YUIProperty_Items ) return YPropertyValue( YOtherProperty );
268  else if ( propertyName == YUIProperty_ItemStatus ) return YPropertyValue( YOtherProperty );
269  else if ( propertyName == YUIProperty_VisibleItems ) return YPropertyValue( visibleItems() );
270  else if ( propertyName == YUIProperty_IconPath ) return YPropertyValue( iconBasePath() );
271  else
272  {
273  return YWidget::getProperty( propertyName );
274  }
275 }
Class describing a non-binary status for an item.
int nextStatus() const
This returns the next status to cycle through if the user clicks on the status or cycles through stat...
void setNextStatus(int value)
Set the next status.
virtual void setVisibleItems(int newVal)
Set the number of visible items.
int visibleItems() const
Return the number of visible items (i.e.
virtual bool setProperty(const std::string &propertyName, const YPropertyValue &val)
Set a property.
int customStatusCount() const
Return the number of custom status values or 0 if no custom status values are used.
virtual YPropertyValue getProperty(const std::string &propertyName)
Get a property.
virtual const YPropertySet & propertySet()
Return this class's property set.
int cycleCustomStatus(int oldStatus)
Cycle through the custom status values according to the custom status table, i.e.
YItemSelector(YWidget *parent, bool enforceSingleSelection=true)
Standard constructor.
bool validCustomStatusIndex(int index) const
Return 'true' if a custom status index is within the valid range, i.e.
virtual const char * widgetClass() const
Return a descriptive name of this widget class for logging, debugging etc.
const YItemCustomStatus & customStatus(int index)
Return the custom status with the specified index (counting from 0).
virtual void setItemStatus(YItem *item, int status)
Set the status of an item.
virtual void updateCustomStatusIndicator(YItem *item)
Update the status indicator (status icon or text indicator) if this widget is using custom status val...
bool usingCustomStatus() const
Return 'true' if this widget uses custom status values, 'false' if not (i.e.
virtual ~YItemSelector()
Destructor.
Simple item class for SelectionBox, ComboBox, MultiSelectionBox etc.
Definition: YItem.h:50
void setStatus(int newStatus)
Set the status of this item.
Definition: YItem.h:128
A set of properties to check names and types against.
Definition: YProperty.h:198
void check(const std::string &propertyName) const
Check if a property 'propertyName' exists in this property set.
Definition: YProperty.cc:88
bool isEmpty() const
Returns 'true' if this property set does not contain anything.
Definition: YProperty.h:263
void add(const YProperty &prop)
Add a property to this property set.
Definition: YProperty.cc:146
Transport class for the value of simple properties.
Definition: YProperty.h:105
std::string stringVal() const
Methods to get the value of this property.
Definition: YProperty.h:180
YPropertyType type() const
Returns the type of this property value.
Definition: YProperty.h:169
Class for widget properties.
Definition: YProperty.h:52
Base class for various kinds of multi-value widgets.
bool enforceSingleSelection() const
Return 'true' if this base class should enforce single selection.
std::string iconBasePath() const
Return this widget's base path where to look up icons as set with setIconBasePath().
virtual void setItemStatus(YItem *item, int status)
Set the status of an item.
void setEnforceInitialSelection(bool on)
In single selection mode, enforce selecting an initial item ('true' by default).
void setIconBasePath(const std::string &basePath)
Set this widget's base path where to look up icons.
Base class for UI Exceptions.
Definition: YUIException.h:298
Abstract base class of all UI widgets.
Definition: YWidget.h:55
virtual const YPropertySet & propertySet()
Return this class's property set.
Definition: YWidget.cc:395
void setDefaultStretchable(YUIDimension dim, bool newStretch)
Set the stretchable state to "newStretch".
Definition: YWidget.cc:566
virtual bool setProperty(const std::string &propertyName, const YPropertyValue &val)
Set a property.
Definition: YWidget.cc:432
virtual YPropertyValue getProperty(const std::string &propertyName)
Get a property.
Definition: YWidget.cc:457