--- Tix_python2.5_orig.py 2006-07-13 23:08:27.000000000 +0200 +++ Tix2.py 2006-07-14 16:12:47.246847968 +0200 @@ -1773,6 +1773,20 @@ # FIXME: It should inherit -superclass tixScrolledWidget pass +# a few useful constants for the Grid widget +ASCII = 'ascii' +CELL = 'cell' +COLUMN = 'column' +DECREASING = 'decreasing' +INCREASING = 'increasing' +INTEGER = 'integer' +MAIN = 'main' +MAX = 'max' +REAL = 'real' +ROW = 'row' +S_REGION = 's-region' +X_REGION = 'x-region' +Y_REGION = 'y-region' class Grid(TixWidget): '''The Tix Grid command creates a new window and makes it into a @@ -1787,7 +1801,64 @@ formatted with a wide range of attributes, such as its color, relief and border. - Subwidgets - None''' + Subwidgets - None + STANDARD OPTIONS + background borderwidth cursor font foreground height + highlightbackground highlightcolor highlightthickness padx pady + relief selectbackground selectborderwidth selectforeground + state takefocus width xscrollcommand yscrollcommand + + WIDGET-SPECIFIC OPTIONS + editdonecmd - If non-empty, gives a command to be executed when + the user has edited a grid cell. When this command is called, + it is passed with two additional parameters: x,y , where + (x,y) is the location of the cell that has just been edited. + editnotifycmd - If non-empty, gives a command to be executed when + the user tries to edit a grid cell. When this command is + called, it is passed with two additional parameters: x, y, + where (x,y) is the location of the cell. This command + should return a boolean value: True indicates that the cell + is editable and False otherwise. + floatingcols - ??? Requires a boolean. The default value is 0. ??? + floatingrows - ??? Requires a boolean. The default value is 0. ??? + formatcmd - If non-empty, gives a command to be executed when + the grid cells need to be formatted on the screen. Normally, + this command calls the format() widget command . When + this command is called, it is passed with five additional + parameters: type x1 y1 x2 y2. type gives the logical type of + the region in the grid. + It may be one of the following. + "x-region": the horizontal margin (as defined with + topmargin); + "y-region": the vertical margin (as defined with + leftmargin); + "s-region", the area where the horizontal and vertical + margins are joined; + "main": all the cells that do not fall into the above + three types. + x1 y1 x2 y2 gives the extent of the region that needs + formatting. + itemtype - the default type of newly created grid cell items; + may be "text" or "image"; default is "text" + leftmargin - In the number of cells, gives the width of vertical + margin. A zero indicates that no vertical should be drawn + (default: 1). Defines the number of columns that are fixed + when the widget is horizontally scrolled. These column(s) can + be used as label(s) for the row(s). + selectmode - Specifies one of several styles for manipulating + the selection. The value of the option may be arbitrary, but + the default bindings expect it to be either "single", + "browse", "multiple", or "extended"; the default value is + "single". + selectunit - Specifies the selection unit. Valid values are + "cell", "column" or "row". + sizecmd - ??? A command that is called whenever a grid cell is + resized ??? + topmargin - In the number of cells, gives the height of horizontal + margin. A zero indicates that no horizontal should be drawn + (default: 1). Defines the number of rows that are fixed when + the widget is vertically scrolled. + These row(s) can be used as label(s) for the column(s).''' # valid specific resources as of Tk 8.4 # editdonecmd, editnotifycmd, floatingcols, floatingrows, formatcmd, # highlightbackground, highlightcolor, leftmargin, itemtype, selectmode, @@ -1798,92 +1869,317 @@ TixWidget.__init__(self, master, 'tixGrid', static, cnf, kw) # valid options as of Tk 8.4 - # anchor, bdtype, cget, configure, delete, dragsite, dropsite, entrycget, edit + # anchor, bdtype, cget, configure, delete, dragsite, dropsite, entrycget,edit # entryconfigure, format, geometryinfo, info, index, move, nearest, selection # set, size, unset, xview, yview - # def anchor option ?args ...? + def anchor_clear(self): + '''Removes the selection anchor.''' + self.tk.call(self._w, 'anchor', 'clear') + def anchor_get(self): "Get the (x,y) coordinate of the current anchor cell" - return self._getints(self.tk.call(self, 'anchor', 'get')) + return self._getints(self.tk.call(self._w, 'anchor', 'get')) + + def anchor_set(self, x, y): + '''Set the selection anchor to the cell at (x, y).''' + self.tk.call(self._w, 'anchor', 'set', x, y) + + def bdtype(self, x, y, xbdWidth=None, ybdWidth=None): + # what is this for? the widget accepts the command + # but I cannot see any effect + return self.tk.call(self._w, 'bdtype', x, y, xbdWidth, ybdWidth) - # def bdtype - # def delete dim from ?to? def delete_row(self, from_, to=None): """Delete rows between from_ and to inclusive. If to is not provided, delete only row at from_""" - if to is None: - self.tk.call(self, 'delete', 'row', from_) - else: - self.tk.call(self, 'delete', 'row', from_, to) + self.tk.call(self._w, 'delete', 'row', from_, to) + def delete_column(self, from_, to=None): """Delete columns between from_ and to inclusive. If to is not provided, delete only column at from_""" - if to is None: - self.tk.call(self, 'delete', 'column', from_) - else: - self.tk.call(self, 'delete', 'column', from_, to) - # def edit apply - # def edit set x y + self.tk.call(self._w, 'delete', 'column', from_, to) + + # dragsite and dropsite are not documented in the tix manpage, + # but they seem to do at least *something* + def dragsite_clear(self): + self.tk.call(self._w, 'dragsite', 'clear') + + def dragsite_get(self): + return self._getints(self.tk.call(self._w, 'dragsite', 'get')) + + def dragsite_set(self, x, y): + self.tk.call(self._w, 'dragsite', 'set', x, y) + + def dropsite_clear(self): + self.tk.call(self._w, 'dropsite', 'clear') + + def dropsite_get(self): + return self._getints(self.tk.call(self._w, 'dropsite', 'get')) + + def dropsite_set(self, x, y): + self.tk.call(self._w, 'dropsite', 'set', x, y) + + def edit_apply(self): + '''If any cell is being edited, de-highlight the cell and applies + the changes.''' + self.tk.call(self._w, 'edit', 'apply') + + def edit_set(self, x, y): + '''Highlights the cell at (x, y) for editing, if the -editnotify + command returns True for this cell.''' + self.tk.call(self._w, 'edit', 'set', x, y) def entrycget(self, x, y, option): "Get the option value for cell at (x,y)" - return self.tk.call(self, 'entrycget', x, y, option) + return self.tk.call(self._w, 'entrycget', x, y, '-'+option) - def entryconfigure(self, x, y, **kw): - return self.tk.call(self, 'entryconfigure', x, y, *self._options(None, kw)) - # def format - # def index + def entryconfigure(self, x, y, cnf=None, **kw): + '''Query or modify the configuration options of the cell at (x,y). + If no option is specified, returns a list describing all of the + available options for the cell. If + one or more option-value pairs are specified, then the command + modifies the given widget option(s) to have the given value(s); + in this case the command returns an empty string.''' + return self._configure(('entryconfigure', x, y), cnf, kw) + entryconfig = entryconfigure + + def format_border(self, x0, y0, x1, y1, **kw): + '''The format_border() method can only be called by the formatcmd + callback of the widget. + Formats the border of the grid cells from (x0, y0) through (x1, y1). + Possible options are: + filled - boolean + xon - int + xoff - int + yon - int + yoff - int + relief, bg, bd, selectbackground etc.''' + self.tk.call(self._w, 'format', 'border', x0, y0, x1, y1, + *self._options({}, kw)) + + def format_grid(self, x0, y0, x1, y1, **kw): + '''The format_grid() method can only be called by the formatcmd + callback of the widget. + Formats the grid cells from (x0, y0) through (x1, y1). + Possible options are: + bordercolor - color + filled - boolean + xon - int + xoff - int + yon - int + yoff - int + bg, selectbackground, anchor etc.''' + self.tk.call(self._w, 'format', 'grid', x0, y0, x1, y1, + *self._options({}, kw)) + + # geometryinfo is not documented, and though it seems to work I cannot + # find the use of this command + def geometryinfo(self, width=None, height=None): + # returns a tuple of the form ((x0, x1), (y0, y1)) + # has this really to be done like this? + return tuple([self._getdoubles(x) for x in self.tk.split( + self.tk.call(self._w, 'geometryinfo', width, height))]) + + def index(self, x, y): + '''Return a tuple of the form (x, y) describing the grid cell at + index (x, y). x and y may be "max" (i.e. the last defined column + resp. row) or "end" (i.e. max + 1).''' + # x or y may be "end" or "max" instead of a numerical index; + # is this all of this method's use? + return self._getints(self.tk.call(self._w, 'index', x, y)) + # info is not documented, maybe because info_bbox() does not seem + # to have any effect; info_exists seems to work well def info_exists(self, x, y): "Return True if display item exists at (x,y)" - return bool(int(self.tk.call(self, 'info', 'exists', x, y))) + return self._getboolean(self.tk.call(self._w, 'info', 'exists', x, y)) def info_bbox(self, x, y): # This seems to always return '', at least for 'text' displayitems - return self.tk.call(self, 'info', 'bbox', x, y) + return self.tk.call(self._w, 'info', 'bbox', x, y) + + def move_column(self, from_, to, offset): + '''Moves the the range of columns from position FROM through TO by + the distance indicated by OFFSET. For example, move_column(2, 4, 1) + moves the columns 2,3,4 to columns 3,4,5.''' + self.tk.call(self._w, 'move', 'column', from_, to, offset) + + def move_row(self, from_, to, offset): + '''Moves the the range of rows + from position FROM through TO by the distance indicated by OFFSET. + For example, move_row(2, 4, 1) moves the rows 2,3,4 to rows 3,4,5.''' + self.tk.call(self._w, 'move', 'row', from_, to, offset) def nearest(self, x, y): "Return coordinate of cell nearest pixel coordinate (x,y)" - return self._getints(self.tk.call(self, 'nearest', x, y)) - - # def selection adjust - # def selection clear - # def selection includes - # def selection set - # def selection toggle - # def move dim from to offset - - def set(self, x, y, itemtype=None, **kw): - args= self._options(self.cnf, kw) - if itemtype is not None: - args= ('-itemtype', itemtype) + args - self.tk.call(self, 'set', x, y, *args) + return self._getints(self.tk.call(self._w, 'nearest', x, y)) - # def size dim index ?option value ...? - # def unset x y - - def xview(self): - return self._getdoubles(self.tk.call(self, 'xview')) + # selection methods are not documented in the man page + # maybe this is because only adjust, set and toggle (and partially clear) + # seem to work + def selection_adjust(self, x0, y0, x1=None, y1=None): + '''Removes the selection from all grid cells and adds the cell + at (x0, y0) to the selection; if x1 and y1 are given, adds the range + of cells from (x0, y0) through (x1, y1) to the selection.''' + self.tk.call(self._w, 'selection', 'adjust', x0, y0, x1, y1) + select_adjust = selection_adjust + + def selection_clear(self, x0=0, y0=0, x1='max', y1='max'): + # this seems to work only with selection_clear(0, 0, 'max', 'max'), + # which removes any selection + '''Removes the selection from all grid cells.''' + self.tk.call(self._w, 'selection', 'clear', x0, y0, x1, y1) + select_clear = selection_clear + + def selection_includes(self, x, y): + # this does not seem to have any effect + '''Returns True if the grid cell at (x, y) is currently selected, + else returns False.''' + return self._getboolean(self.tk.call( + self._w, 'selection', 'includes', x, y)) + select_includes = selection_includes + + def selection_set(self, x0, y0, x1=None, y1=None): + '''Adds the cell at (x0, y0) to the selection; if x1 and y1 are given, + adds the range of cells from (x0, y0) through (x1, y1) to + the selection.''' + self.tk.call(self._w, 'selection', 'set', x0, y0, x1, y1) + select_set = selection_set + + def selection_toggle(self, x0, y0, x1=None, y1=None): + '''Changes the state of selection for the cell at (x0, y0); + if x1 and y1 are given, changes the state of selection for the range + of cells from (x0, y0) through (x1, y1).''' + self.tk.call(self._w, 'selection', 'toggle', x0, y0, x1, y1) + select_toggle = selection_toggle + + def set(self, x, y, **kw): + '''Creates a new display item at the cell at (x, y). The optional + -itemtype parameter gives the type of the display item + ("text" or "image"). An additional list of option-value pairs + specify options of the display item. If a display item already exists + at this cell, the old item will be deleted automatically. + Possible options for text items are: + text, style, underline + Possible options for image items are: + image, style.''' + self.tk.call(self._w, 'set', x, y, *self._options({}, kw)) + + def size_column(self, index, **kw): + '''Queries or sets the size of the column given by + INDEX. INDEX may be any non-negative + integer that gives the position of a given column. + INDEX can also be the string "default"; in this case, this command + queries or sets the default size of all columns. + When no option-value pair is given, this command returns a tuple + containing the current size setting of the given column. When + option-value pairs are given, the corresponding options of the + size setting of the given column are changed. Options may be one + of the follwing: + pad0 pixels + Specifies the paddings to the left of a column. + pad1 pixels + Specifies the paddings to the right of a column. + size val + Specifies the width of a column . + Val may be: "auto" -- the width of the column is set the + the widest cell in the column; a valid Tk screen distance + unit (see Tk_GetPixels(n)); or a real number following by + the word chars (e.g. 3.4chars) that sets the width of the + column to the given number of characters.''' + return self.tk.split(self.tk.call(self._w, 'size', 'column', index, + *self._options({}, kw))) + + def size_row(self, index, **kw): + '''Queries or sets the size of the row given by + INDEX. INDEX may be any non-negative + integer that gives the position of a given row . + INDEX can also be the string "default"; in this case, this command + queries or sets the default size of all rows. + When no option-value pair is given, this command returns a list con- + taining the current size setting of the given row . When option-value + pairs are given, the corresponding options of the size setting of the + given row are changed. Options may be one of the follwing: + pad0 pixels + Specifies the paddings to the top of a row. + pad1 pixels + Specifies the paddings to the the bottom of a row. + size val + Specifies the height of a row. + Val may be: "auto" -- the height of the row is set the + the highest cell in the row; a valid Tk screen distance + unit (see Tk_GetPixels(n)); or a real number following by + the word chars (e.g. 3.4chars) that sets the height of + the row to the given number of characters.''' + return self.tk.split(self.tk.call( + self._w, 'size', 'row', index, *self._options({}, kw))) + + # sort is not documented, but the the widget accepts the command + # and it seems to work at least for the most part + def sort_column(self, first, last, **kw): + '''Sorts columns in the range from FIRST through LAST, + according to the given options. + Possible options are: + command : a tcl command that accepts two items as arguments, + compares these and returns a proper boolean value. + key : the index of the row to compare the items' values from. + order : must be "increasing" or "decreasing". + type : must be "ascii", "integer" or "real".''' + self.tk.call(self._w, 'sort', 'column', first, last, + *self._options({}, kw)) + + def sort_row(self, first, last, **kw): + '''Sorts rows in the range from FIRST through LAST, + according to the given options. + Possible options are: + command : a tcl command that accepts two items as arguments, + compares these and returns a proper boolean value. + key : the index of the column to compare the items' values + from. + order : must be "increasing" or "decreasing". + type : must be "ascii", "integer" or "real".''' + self.tk.call(self._w, 'sort', 'row', first, last, + *self._options({}, kw)) + + def unset(self, x, y): + '''Clears the cell at (x, y) by removing its display item.''' + self.tk.call(self._w, 'unset', x, y) + + def xview(self, *what): + if not what: + return self._getdoubles(self.tk.call(self._w, 'xview')) + self.tk.call((self._w, 'xview') + what) def xview_moveto(self, fraction): - self.tk.call(self,'xview', 'moveto', fraction) + self.tk.call(self._w,'xview', 'moveto', fraction) def xview_scroll(self, count, what="units"): - "Scroll right (count>0) or left of units|pages" - self.tk.call(self, 'xview', 'scroll', count, what) + "Scroll right (count>0) or left (count<0) of units|pages" + self.tk.call(self._w, 'xview', 'scroll', count, what) - def yview(self): - return self._getdoubles(self.tk.call(self, 'yview')) + def yview(self, *what): + if not what: + return self._getdoubles(self.tk.call(self._w, 'yview')) + self.tk.call((self._w, 'yview') + what) def yview_moveto(self, fraction): - self.tk.call(self,'ysview', 'moveto', fraction) + self.tk.call(self._w,'yview', 'moveto', fraction) def yview_scroll(self, count, what="units"): - "Scroll down (count>0) or up of units|pages" - self.tk.call(self, 'yview', 'scroll', count, what) + "Scroll down (count>0) or up (count>0) of units|pages" + self.tk.call(self._w, 'yview', 'scroll', count, what) + +class _dummyGrid(Grid, TixSubWidget): + def __init__(self, master, name, destroy_physically=1): + TixSubWidget.__init__(self, master, name, destroy_physically) class ScrolledGrid(Grid): '''Scrolled Grid widgets''' - # FIXME: It should inherit -superclass tixScrolledWidget def __init__(self, master=None, cnf={}, **kw): static= [] self.cnf= cnf TixWidget.__init__(self, master, 'tixScrolledGrid', static, cnf, kw) - + self.subwidget_list['grid'] = _dummyGrid(self, 'grid') + self.subwidget_list['vsb'] = _dummyScrollbar(self, 'vsb') + self.subwidget_list['hsb'] = _dummyScrollbar(self, 'hsb') + # we cannot use the self.grid shortcut to access the Grid subwidget + # here because it conflicts with the grid() geometry method, + # so add a grid_ attribute as a replacement + self.grid_ = self.subwidget('grid')