mrv.maya.ui.control
Covered: 282 lines
Missed: 40 lines
Skipped 130 lines
Percent: 87 %
  2
"""
  3
Contains the most controls like buttons and sliders for more convenient use
  4
"""
  5
__docformat__ = "restructuredtext"
  7
import base as uibase
  8
import util as uiutil
 10
from mrv.maya.util import noneToList
 12
import logging
 13
log = logging.getLogger("mrv.maya.ui.control")
 17
class LabelBase( uibase.SizedControl ):
 18
	"""Base class for elements having labels"""
 19
	_properties_ = ( 	"l", "label",
 20
						"al", "align" ,
 21
						"rs", "recomputeSize" )
 23
class SliderBase( uibase.SizedControl ):
 24
	"""Class contributing Simple Slider Events"""
 25
	_events_ = ( 	"cc", "changeCommand",
 26
					"dc", "dragCommand" )
 28
	_properties_ = ( 	"min", "minValue",
 29
					  	"max", "maxValue",
 30
						"v", "value",
 31
						"s", "step",
 32
						"hr", "horizontal" )
 34
class BooleanBase( LabelBase ):
 35
	"""Base class for boolean controls"""
 36
	_events_ = ( 	"onCommand", "onc",
 37
					"offCommand", "ofc",
 38
					"changeCommand", "cc" )
 40
class CheckBoxBase( BooleanBase ):
 41
	"""Base class for checkboxes"""
 42
	_properties_ = ( "value", "v" )
 44
class RadioButtonBase( BooleanBase ):
 45
	"""Base class for radio buttons"""
 46
	_properties_ = ( "select", "sl" )
 49
class GroupBase( uibase.SizedControl ):
 50
	"""Base allowing access to all grouped controls
 52
	:note: using short property names to ... keep it sane """
 54
	_properties_ = [ 	"cw", "columnWidth",
 55
						"cat", "columnAttach",
 56
						"rat", "rowAttach",
 57
						"cal", "columnAlign",
 58
						"adj", "adjustableColumn" ]
 61
	for flag in ( 	"cw","columnWidth", "ct", "columnAttach",
 62
				  	"co", "columnOffset", "cl", "columnAlign",
 63
					"ad", "adjustableColumn" ):
 64
		start = 1
 65
		if flag in ( "cl", "columnAlign", "ad", "adjustableColumn" ):
 66
			start = 2
 68
		for i in range( start, 7 ):
 69
			_properties_.append( flag + str( i ) )
 72
class OptionMenuBase( uibase.ContainerMenuBase ):
 73
	"""base class for all optionMenu like controls"""
 74
	__metaclass__ = uibase.typ.MetaClassCreatorUI
 76
	_events_ = ( "cc", "changeCommand" )
 77
	_properties_ = ( 	"ils", "itemListShort",
 78
						"ill", "itemListLong",
 79
						"l", "label",
 80
						"ni", "numberOfItems",
 81
						"sl", "select",
 82
						"v", "value" )
 84
class FieldBase( uibase.SizedControl ):
 85
	_events_ = 		( 	"rfc", "receiveFocusCommand",
 86
						"ec", "enterCommand",
 87
						"cc", "changeCommand" )
 89
	_properties_ = ( "ed", "editable" )
 92
class TextFieldBase( object ):
 93
	"""Base just containing properties and events"""
 94
	__metaclass__ = uibase.typ.MetaClassCreatorUI
 96
	_properties_ = ( 	"fn", "font",
 97
						"it", "insertText",
 98
						"ip", "insertPosition"
 99
						"fi", "fileName",
100
						"tx", "text" )
102
class TextFieldGroupBase( TextFieldBase ):
103
	"""Common base for the group text fields"""
104
	_events_ = ( 	"cc", "changeCommand" ,
105
					"fcc", "forceChangeCommand" )
107
class SliderGroupBase( GroupBase, SliderBase ):
108
	"""base class for all sliders"""
109
	_properties_ = ( 	"el", "extraLabel",
110
						"fieldMinValue", "fmn",
111
						"fieldMaxValue", "fmx",
112
						"fieldStep", "fs",
113
						"sliderStep", "ss" )
116
class BooleanGroupBase( GroupBase, BooleanBase ):
117
	"""base class for all boolean groups"""
118
	_events_ = list()
121
	for flag in ( 	"on","onCommand",
122
				  	"of", "offCommand",
123
					"cc", "changeCommand" ):
125
		for i in range( 1, 5 ):
126
			_events_.append( flag + str( i ) )
129
	_properties_ = list()
131
	for flag in ( 	"en","enable",
132
				  	"da", "data",
133
					"l", "label",
134
					"la","labelArray" ):
136
		start = 1
137
		if flag in ( "la", "labelArray" ):
138
			start = 2
140
		for i in range( start, 5 ):
141
			_properties_.append( flag + str( i ) )
145
class ButtonGroupBase( GroupBase ):
146
	"""Base class for all button groups"""
147
	_properties_ = ( 	"bl", "buttonLabel",
148
						"eb", "enableButton" )
150
	_events_ = ( "bc", "buttonCommand" )
152
class IconTextBase( object ):
153
	"""Base class for all icon text like controls"""
155
	__metaclass__ = uibase.typ.MetaClassCreatorUI
158
	_properties_ = ( 	"image", "i",
159
					  	"image1", "i1",
160
						"image2", "i2",
161
						"image3", "i3",
162
						"disabledImage", "di",
163
						"highlightImage", "hi",
164
						"imageOverlayLabel", "iol",
165
						"style", "st",
166
						"selectionImage", "si",
167
						"highlightImage", "hi",
168
						"labelOffset", "lo",
169
						"font", "fn"
170
						)
172
	_events_ = ( 		"handleNodeDropCallback", "hnd",
173
					 	"labelEditingCallback", "lec"	)
178
class RadioButtonGrp( BooleanGroupBase, RadioButtonBase ):
179
	"""Warning: inherits booleanBase multiple times """
180
	pass
183
class CheckBoxGrp( BooleanGroupBase, CheckBoxBase ):
184
	"""Note: inherits booleanBase multiple times, this does no harm"""
185
	_properties_ = list()
187
	for flag in ( 	"v","value",
188
				  	"va", "valueArray" ):
189
		for i in range( 1, 5 ):
190
			if flag in ( "va", "valueArray" ) and i == 1:
191
				continue
193
			_properties_.append( flag + str( i ) )
198
class Button( LabelBase ):
199
	""" Simple button interface
201
	:note: you can only use either the onpress or the onrelease event, both
202
		together apparently do not work"""
203
	_properties_ = ( "actionIsSubstitute" )
204
	_events_ = ( "c", "command" )
206
	e_pressed = uiutil.EventSenderUI._UIEvent( "command", actOnPress=True )
207
	e_released = uiutil.EventSenderUI._UIEvent( "command", actOnPress=False )
210
class IconTextButton( LabelBase, IconTextBase ):
211
	"""Class just for multiple inheritance - this cannot be expressed in the hierarchy
212
	file"""
213
	_events_ = ( "c", "command" )
216
class RadioCollectionBase( object ):
217
	"""Keeps common properties"""
218
	__metaclass__ = uibase.typ.MetaClassCreatorUI
220
	_properties_ = ( 	"global", "gl",
221
						"select", "sl", 
222
						"disableCommands", "dcm", 
223
						"numberOfCollectionItems", "nci", 
224
						"collectionItemArray", "cia" )
227
class RadioCollection( RadioCollectionBase, uibase.NamedUI ):
228
	"""Required for multiple inhertance"""
229
	pass
232
class IconTextRadioCollection( RadioCollectionBase, uibase.NamedUI ):
233
	"""Required for multiple inhertance
234
	:note: it inherits exists() and a few others which are actually not supported for 
235
	some reason"""
236
	pass
239
class ToolCollection( RadioCollectionBase, uibase.NamedUI ):
240
	"""Required for multiple inhertance"""
241
	pass
244
class RadioMenuItemCollection( RadioCollectionBase, uibase.NamedUI ):
245
	"""Required for multiple inhertance"""
246
	pass
249
class IconTextCheckBox( CheckBoxBase, IconTextBase ):
250
	"""Class just for multiple inheritance - this cannot be expressed in the hierarchy
251
	file"""
252
	pass
254
class IconTextRadioButton( RadioButtonBase, IconTextBase ):
255
	"""Class just for multiple inheritance - this cannot be expressed in the hierarchy
256
	file"""
257
	pass
259
class TextField( FieldBase, TextFieldBase ):
260
	"""Class just for multiple inheritance - this cannot be expressed in the hierarchy
261
	file"""
262
	pass
264
class ScrollField( uibase.SizedControl ):
265
	""":note: although the class shares some properties of the textfield, it does not share all of them"""
266
	_properties_ = ( 	"wordWrap", "ww",
267
					  	"font", 	"fn",
268
						"text", "tx",
269
						"insertText", "it",
270
						"insertionPosition", "ip",
271
						"selection", "sl",
272
						"clear", "cl",
273
						"editable", "ed",
274
						"numberOfLines", "nl"	)
276
	_events_ = ( 		"enterCommand", "ec",
277
					 	"keyPressCommand", "kpc",
278
						"changeCommand", "cc"		)
281
class TextScrollList( uibase.SizedControl ):
282
	"""Class defining attributes and events for the text-scroll list"""
283
	_properties_ = ( 	"append", "a",
284
						"appendPosition", "ap",
285
						"allItems", "ai",
286
						"allowAutomaticSelection", "aas",
287
						"allowMultiSelection", "ams",
288
						"numberOfItems", "ni",
289
						"numberOfRows", "nr",
290
						"numberOfSelectedItems", "nsi",
291
						"removeAll", "ra"
292
						"removeItem", "ri",
293
						"removeIndexedItem", "rii",
294
						"selectItem", "si",
295
						"selectIndexedItem", "sii",
296
						"deselectAll", "da",
297
						"deselectItem", "di",
298
						"deselectIndexedItem", "dii",
299
						"showIndexedItem", "shi",
300
						"font", "fn" )
302
	_events_ = ( 	"doubleClickCommand", "dcc",
303
					"deleteKeyCommand", "dkc",
304
					"selectCommand", "sc" )
308
	def items(self):
309
		""":return: list of currently available items"""
310
		return noneToList(self.p_allItems)
312
	def selectedIndex(self):
313
		""":return: First selected index - the index is 1-based, or -1 if there 
314
		is nothing selected
315
		:note: even if multiple selections are possible"""
316
		sel = self.selectedIndices()
317
		if not sel:
318
			return -1
319
		return sel[0]
321
	def selectedIndices(self):
322
		""":return: tuple of all selected 1-based indices, or an empty tuple if there
323
			is nothing selected"""
324
		try:
325
			return tuple(noneToList(self.p_selectIndexedItem))
326
		except RuntimeError:
327
			return tuple()
330
	def selectedItem(self):
331
		""":return: the first selected item, or None if nothing is selected"""
332
		items = self.selectedItems()
333
		return (items and items[0]) or None
335
	def selectedItems(self):
336
		""":return: list of all selected items as strings, or an empty list if nothing
337
			is selected"""
338
		try:
339
			return noneToList(self.p_selectItem)
340
		except RuntimeError:
341
			return list()
344
	def setItems(self, items):
345
		"""Set the given items to be shown.
346
		:param items: iterable of items 
347
			if empty, the control will be empty after this call.
348
		:return: self"""
349
		self.p_removeAll = True
350
		for item in items:
351
			self.p_append = str(item)
353
		return self
355
	def addItem(self, item):
356
		"""Add the given item to the end of the list
357
		:return: self"""
358
		self.p_append = str(item)
359
		return self
361
	def addItems(self, items):
362
		"""Add multiple items to the end of the list
363
		:return: self"""
364
		for item in items:
365
			self.addItem(item)
367
		return self
369
	def setSelectedItem(self, item):
370
		"""Set the given item selected, or clear the selection
371
		:param item: item to select, or clear the selection if None is given
372
		:note: it is not considered an error if the item doesnt exist - following 
373
			maya's behaviour
374
		:return: self"""
375
		if item is None:
376
			self.p_deselectAll = True
377
			return
380
		self.p_selectItem = item
381
		return self
383
	def removeItem(self, item):
384
		"""Remove the given item from the list. It is not an error if it doesn't 
385
		exist in the first place
386
		:return: self"""
387
		items = self.items()
388
		try:
389
			index = items.index(item)
390
			self.p_removeIndexedItem = index+1
391
		except ValueError:
393
			pass
395
		return self
401
class TextFieldGrp( GroupBase, TextFieldGroupBase ):
402
	"""Class just for multiple inheritance - this cannot be expressed in the hierarchy
403
	file"""
406
class TextFieldButtonGrp( ButtonGroupBase, TextFieldGroupBase ):
407
	"""Class just for multiple inheritance - this cannot be expressed in the hierarchy
408
	file"""
410
class Text( LabelBase ):
411
	_properties_ = ( "font", "fn" )
413
class Separator( uibase.SizedControl ):
414
	_properties_ = ( 	"style", "st",
415
						"horizontal", "hr" 		)
417
class OptionMenu( OptionMenuBase, uibase.SizedControl ):
418
	"""Class just for multiple inheritance - this cannot be expressed in the hierarchy
419
	file
421
	:note: Order of inheritance matters due to method resolution order !"""
423
	_is_menu = True
427
class OptionMenuGrp( OptionMenuBase, GroupBase ):
428
	"""Class just for multiple inheritance - this cannot be expressed in the hierarchy
429
	file
431
	:note: Order of inheritance matters due to method resolution order !"""
433
	_is_menu = True
438
	def setActive( self ):
439
		"""The optionMenuGrp cannot be set as a parent as it is classified as control layout.
440
		A problem arises if you actually try to add new menuItems to it after it's creation which
441
		does not work as it is not a menu"""
442
		log.warn("setActive: OptionMenuGrp's instances cannot be setActive after creation due to a Maya API logic error - you will set the layout active, not the contained option menu")
443
		return super( OptionMenuGrp, self ).setActive()
445
	def setParentActive( self ):
446
		"""See `setActive`"""
447
		log.warn("setParentActive: OptionMenuGrp instances will change the parent of their control layout only, not the menu parent of the optionMenu")
448
		super( OptionMenuGrp, self ).setParentActive()