symbian-qemu-0.9.1-12/python-2.6.1/Tools/pynche/StripViewer.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 """Strip viewer and related widgets.
       
     2 
       
     3 The classes in this file implement the StripViewer shown in the top two thirds
       
     4 of the main Pynche window.  It consists of three StripWidgets which display
       
     5 the variations in red, green, and blue respectively of the currently selected
       
     6 r/g/b color value.
       
     7 
       
     8 Each StripWidget shows the color variations that are reachable by varying an
       
     9 axis of the currently selected color.  So for example, if the color is
       
    10 
       
    11   (R,G,B)=(127,163,196)
       
    12 
       
    13 then the Red variations show colors from (0,163,196) to (255,163,196), the
       
    14 Green variations show colors from (127,0,196) to (127,255,196), and the Blue
       
    15 variations show colors from (127,163,0) to (127,163,255).
       
    16 
       
    17 The selected color is always visible in all three StripWidgets, and in fact
       
    18 each StripWidget highlights the selected color, and has an arrow pointing to
       
    19 the selected chip, which includes the value along that particular axis.
       
    20 
       
    21 Clicking on any chip in any StripWidget selects that color, and updates all
       
    22 arrows and other windows.  By toggling on Update while dragging, Pynche will
       
    23 select the color under the cursor while you drag it, but be forewarned that
       
    24 this can be slow.
       
    25 """
       
    26 
       
    27 from Tkinter import *
       
    28 import ColorDB
       
    29 
       
    30 # Load this script into the Tcl interpreter and call it in
       
    31 # StripWidget.set_color().  This is about as fast as it can be with the
       
    32 # current _tkinter.c interface, which doesn't support Tcl Objects.
       
    33 TCLPROC = '''\
       
    34 proc setcolor {canv colors} {
       
    35     set i 1
       
    36     foreach c $colors {
       
    37         $canv itemconfigure $i -fill $c -outline $c
       
    38         incr i
       
    39     }
       
    40 }
       
    41 '''
       
    42 
       
    43 # Tcl event types
       
    44 BTNDOWN = 4
       
    45 BTNUP = 5
       
    46 BTNDRAG = 6
       
    47 
       
    48 SPACE = ' '
       
    49 
       
    50 
       
    51 
       
    52 def constant(numchips):
       
    53     step = 255.0 / (numchips - 1)
       
    54     start = 0.0
       
    55     seq = []
       
    56     while numchips > 0:
       
    57         seq.append(int(start))
       
    58         start = start + step
       
    59         numchips = numchips - 1
       
    60     return seq
       
    61 
       
    62 # red variations, green+blue = cyan constant
       
    63 def constant_red_generator(numchips, red, green, blue):
       
    64     seq = constant(numchips)
       
    65     return map(None, [red] * numchips, seq, seq)
       
    66 
       
    67 # green variations, red+blue = magenta constant
       
    68 def constant_green_generator(numchips, red, green, blue):
       
    69     seq = constant(numchips)
       
    70     return map(None, seq, [green] * numchips, seq)
       
    71 
       
    72 # blue variations, red+green = yellow constant
       
    73 def constant_blue_generator(numchips, red, green, blue):
       
    74     seq = constant(numchips)
       
    75     return map(None, seq, seq, [blue] * numchips)
       
    76 
       
    77 # red variations, green+blue = cyan constant
       
    78 def constant_cyan_generator(numchips, red, green, blue):
       
    79     seq = constant(numchips)
       
    80     return map(None, seq, [green] * numchips, [blue] * numchips)
       
    81 
       
    82 # green variations, red+blue = magenta constant
       
    83 def constant_magenta_generator(numchips, red, green, blue):
       
    84     seq = constant(numchips)
       
    85     return map(None, [red] * numchips, seq, [blue] * numchips)
       
    86 
       
    87 # blue variations, red+green = yellow constant
       
    88 def constant_yellow_generator(numchips, red, green, blue):
       
    89     seq = constant(numchips)
       
    90     return map(None, [red] * numchips, [green] * numchips, seq)
       
    91 
       
    92 
       
    93 
       
    94 class LeftArrow:
       
    95     _ARROWWIDTH = 30
       
    96     _ARROWHEIGHT = 15
       
    97     _YOFFSET = 13
       
    98     _TEXTYOFFSET = 1
       
    99     _TAG = ('leftarrow',)
       
   100 
       
   101     def __init__(self, canvas, x):
       
   102         self._canvas = canvas
       
   103         self.__arrow, self.__text = self._create(x)
       
   104         self.move_to(x)
       
   105 
       
   106     def _create(self, x):
       
   107         arrow = self._canvas.create_line(
       
   108             x, self._ARROWHEIGHT + self._YOFFSET,
       
   109             x, self._YOFFSET,
       
   110             x + self._ARROWWIDTH, self._YOFFSET,
       
   111             arrow='first',
       
   112             width=3.0,
       
   113             tags=self._TAG)
       
   114         text = self._canvas.create_text(
       
   115             x + self._ARROWWIDTH + 13,
       
   116             self._ARROWHEIGHT - self._TEXTYOFFSET,
       
   117             tags=self._TAG,
       
   118             text='128')
       
   119         return arrow, text
       
   120 
       
   121     def _x(self):
       
   122         coords = self._canvas.coords(self._TAG)
       
   123         assert coords
       
   124         return coords[0]
       
   125 
       
   126     def move_to(self, x):
       
   127         deltax = x - self._x()
       
   128         self._canvas.move(self._TAG, deltax, 0)
       
   129 
       
   130     def set_text(self, text):
       
   131         self._canvas.itemconfigure(self.__text, text=text)
       
   132 
       
   133 
       
   134 class RightArrow(LeftArrow):
       
   135     _TAG = ('rightarrow',)
       
   136 
       
   137     def _create(self, x):
       
   138         arrow = self._canvas.create_line(
       
   139             x, self._YOFFSET,
       
   140             x + self._ARROWWIDTH, self._YOFFSET,
       
   141             x + self._ARROWWIDTH, self._ARROWHEIGHT + self._YOFFSET,
       
   142             arrow='last',
       
   143             width=3.0,
       
   144             tags=self._TAG)
       
   145         text = self._canvas.create_text(
       
   146             x - self._ARROWWIDTH + 15,            # BAW: kludge
       
   147             self._ARROWHEIGHT - self._TEXTYOFFSET,
       
   148             justify=RIGHT,
       
   149             text='128',
       
   150             tags=self._TAG)
       
   151         return arrow, text
       
   152 
       
   153     def _x(self):
       
   154         coords = self._canvas.coords(self._TAG)
       
   155         assert coords
       
   156         return coords[0] + self._ARROWWIDTH
       
   157 
       
   158 
       
   159 
       
   160 class StripWidget:
       
   161     _CHIPHEIGHT = 50
       
   162     _CHIPWIDTH = 10
       
   163     _NUMCHIPS = 40
       
   164 
       
   165     def __init__(self, switchboard,
       
   166                  master     = None,
       
   167                  chipwidth  = _CHIPWIDTH,
       
   168                  chipheight = _CHIPHEIGHT,
       
   169                  numchips   = _NUMCHIPS,
       
   170                  generator  = None,
       
   171                  axis       = None,
       
   172                  label      = '',
       
   173                  uwdvar     = None,
       
   174                  hexvar     = None):
       
   175         # instance variables
       
   176         self.__generator = generator
       
   177         self.__axis = axis
       
   178         self.__numchips = numchips
       
   179         assert self.__axis in (0, 1, 2)
       
   180         self.__uwd = uwdvar
       
   181         self.__hexp = hexvar
       
   182         # the last chip selected
       
   183         self.__lastchip = None
       
   184         self.__sb = switchboard
       
   185 
       
   186         canvaswidth = numchips * (chipwidth + 1)
       
   187         canvasheight = chipheight + 43            # BAW: Kludge
       
   188 
       
   189         # create the canvas and pack it
       
   190         canvas = self.__canvas = Canvas(master,
       
   191                                         width=canvaswidth,
       
   192                                         height=canvasheight,
       
   193 ##                                        borderwidth=2,
       
   194 ##                                        relief=GROOVE
       
   195                                         )
       
   196 
       
   197         canvas.pack()
       
   198         canvas.bind('<ButtonPress-1>', self.__select_chip)
       
   199         canvas.bind('<ButtonRelease-1>', self.__select_chip)
       
   200         canvas.bind('<B1-Motion>', self.__select_chip)
       
   201 
       
   202         # Load a proc into the Tcl interpreter.  This is used in the
       
   203         # set_color() method to speed up setting the chip colors.
       
   204         canvas.tk.eval(TCLPROC)
       
   205 
       
   206         # create the color strip
       
   207         chips = self.__chips = []
       
   208         x = 1
       
   209         y = 30
       
   210         tags = ('chip',)
       
   211         for c in range(self.__numchips):
       
   212             color = 'grey'
       
   213             canvas.create_rectangle(
       
   214                 x, y, x+chipwidth, y+chipheight,
       
   215                 fill=color, outline=color,
       
   216                 tags=tags)
       
   217             x = x + chipwidth + 1                 # for outline
       
   218             chips.append(color)
       
   219 
       
   220         # create the strip label
       
   221         self.__label = canvas.create_text(
       
   222             3, y + chipheight + 8,
       
   223             text=label,
       
   224             anchor=W)
       
   225 
       
   226         # create the arrow and text item
       
   227         chipx = self.__arrow_x(0)
       
   228         self.__leftarrow = LeftArrow(canvas, chipx)
       
   229 
       
   230         chipx = self.__arrow_x(len(chips) - 1)
       
   231         self.__rightarrow = RightArrow(canvas, chipx)
       
   232 
       
   233     def __arrow_x(self, chipnum):
       
   234         coords = self.__canvas.coords(chipnum+1)
       
   235         assert coords
       
   236         x0, y0, x1, y1 = coords
       
   237         return (x1 + x0) / 2.0
       
   238 
       
   239     # Invoked when one of the chips is clicked.  This should just tell the
       
   240     # switchboard to set the color on all the output components
       
   241     def __select_chip(self, event=None):
       
   242         x = event.x
       
   243         y = event.y
       
   244         canvas = self.__canvas
       
   245         chip = canvas.find_overlapping(x, y, x, y)
       
   246         if chip and (1 <= chip[0] <= self.__numchips):
       
   247             color = self.__chips[chip[0]-1]
       
   248             red, green, blue = ColorDB.rrggbb_to_triplet(color)
       
   249             etype = int(event.type)
       
   250             if (etype == BTNUP or self.__uwd.get()):
       
   251                 # update everyone
       
   252                 self.__sb.update_views(red, green, blue)
       
   253             else:
       
   254                 # just track the arrows
       
   255                 self.__trackarrow(chip[0], (red, green, blue))
       
   256 
       
   257     def __trackarrow(self, chip, rgbtuple):
       
   258         # invert the last chip
       
   259         if self.__lastchip is not None:
       
   260             color = self.__canvas.itemcget(self.__lastchip, 'fill')
       
   261             self.__canvas.itemconfigure(self.__lastchip, outline=color)
       
   262         self.__lastchip = chip
       
   263         # get the arrow's text
       
   264         coloraxis = rgbtuple[self.__axis]
       
   265         if self.__hexp.get():
       
   266             # hex
       
   267             text = hex(coloraxis)
       
   268         else:
       
   269             # decimal
       
   270             text = repr(coloraxis)
       
   271         # move the arrow, and set its text
       
   272         if coloraxis <= 128:
       
   273             # use the left arrow
       
   274             self.__leftarrow.set_text(text)
       
   275             self.__leftarrow.move_to(self.__arrow_x(chip-1))
       
   276             self.__rightarrow.move_to(-100)
       
   277         else:
       
   278             # use the right arrow
       
   279             self.__rightarrow.set_text(text)
       
   280             self.__rightarrow.move_to(self.__arrow_x(chip-1))
       
   281             self.__leftarrow.move_to(-100)
       
   282         # and set the chip's outline
       
   283         brightness = ColorDB.triplet_to_brightness(rgbtuple)
       
   284         if brightness <= 128:
       
   285             outline = 'white'
       
   286         else:
       
   287             outline = 'black'
       
   288         self.__canvas.itemconfigure(chip, outline=outline)
       
   289 
       
   290 
       
   291     def update_yourself(self, red, green, blue):
       
   292         assert self.__generator
       
   293         i = 1
       
   294         chip = 0
       
   295         chips = self.__chips = []
       
   296         tk = self.__canvas.tk
       
   297         # get the red, green, and blue components for all chips
       
   298         for t in self.__generator(self.__numchips, red, green, blue):
       
   299             rrggbb = ColorDB.triplet_to_rrggbb(t)
       
   300             chips.append(rrggbb)
       
   301             tred, tgreen, tblue = t
       
   302             if tred <= red and tgreen <= green and tblue <= blue:
       
   303                 chip = i
       
   304             i = i + 1
       
   305         # call the raw tcl script
       
   306         colors = SPACE.join(chips)
       
   307         tk.eval('setcolor %s {%s}' % (self.__canvas._w, colors))
       
   308         # move the arrows around
       
   309         self.__trackarrow(chip, (red, green, blue))
       
   310 
       
   311     def set(self, label, generator):
       
   312         self.__canvas.itemconfigure(self.__label, text=label)
       
   313         self.__generator = generator
       
   314 
       
   315 
       
   316 class StripViewer:
       
   317     def __init__(self, switchboard, master=None):
       
   318         self.__sb = switchboard
       
   319         optiondb = switchboard.optiondb()
       
   320         # create a frame inside the master.
       
   321         frame = Frame(master, relief=RAISED, borderwidth=1)
       
   322         frame.grid(row=1, column=0, columnspan=2, sticky='NSEW')
       
   323         # create the options to be used later
       
   324         uwd = self.__uwdvar = BooleanVar()
       
   325         uwd.set(optiondb.get('UPWHILEDRAG', 0))
       
   326         hexp = self.__hexpvar = BooleanVar()
       
   327         hexp.set(optiondb.get('HEXSTRIP', 0))
       
   328         # create the red, green, blue strips inside their own frame
       
   329         frame1 = Frame(frame)
       
   330         frame1.pack(expand=YES, fill=BOTH)
       
   331         self.__reds = StripWidget(switchboard, frame1,
       
   332                                   generator=constant_cyan_generator,
       
   333                                   axis=0,
       
   334                                   label='Red Variations',
       
   335                                   uwdvar=uwd, hexvar=hexp)
       
   336 
       
   337         self.__greens = StripWidget(switchboard, frame1,
       
   338                                     generator=constant_magenta_generator,
       
   339                                     axis=1,
       
   340                                     label='Green Variations',
       
   341                                     uwdvar=uwd, hexvar=hexp)
       
   342 
       
   343         self.__blues = StripWidget(switchboard, frame1,
       
   344                                    generator=constant_yellow_generator,
       
   345                                    axis=2,
       
   346                                    label='Blue Variations',
       
   347                                    uwdvar=uwd, hexvar=hexp)
       
   348 
       
   349         # create a frame to contain the controls
       
   350         frame2 = Frame(frame)
       
   351         frame2.pack(expand=YES, fill=BOTH)
       
   352         frame2.columnconfigure(0, weight=20)
       
   353         frame2.columnconfigure(2, weight=20)
       
   354 
       
   355         padx = 8
       
   356 
       
   357         # create the black button
       
   358         blackbtn = Button(frame2,
       
   359                           text='Black',
       
   360                           command=self.__toblack)
       
   361         blackbtn.grid(row=0, column=0, rowspan=2, sticky=W, padx=padx)
       
   362 
       
   363         # create the controls
       
   364         uwdbtn = Checkbutton(frame2,
       
   365                              text='Update while dragging',
       
   366                              variable=uwd)
       
   367         uwdbtn.grid(row=0, column=1, sticky=W)
       
   368         hexbtn = Checkbutton(frame2,
       
   369                              text='Hexadecimal',
       
   370                              variable=hexp,
       
   371                              command=self.__togglehex)
       
   372         hexbtn.grid(row=1, column=1, sticky=W)
       
   373 
       
   374         # XXX: ignore this feature for now; it doesn't work quite right yet
       
   375 
       
   376 ##        gentypevar = self.__gentypevar = IntVar()
       
   377 ##        self.__variations = Radiobutton(frame,
       
   378 ##                                        text='Variations',
       
   379 ##                                        variable=gentypevar,
       
   380 ##                                        value=0,
       
   381 ##                                        command=self.__togglegentype)
       
   382 ##        self.__variations.grid(row=0, column=1, sticky=W)
       
   383 ##        self.__constants = Radiobutton(frame,
       
   384 ##                                       text='Constants',
       
   385 ##                                       variable=gentypevar,
       
   386 ##                                       value=1,
       
   387 ##                                       command=self.__togglegentype)
       
   388 ##        self.__constants.grid(row=1, column=1, sticky=W)
       
   389 
       
   390         # create the white button
       
   391         whitebtn = Button(frame2,
       
   392                           text='White',
       
   393                           command=self.__towhite)
       
   394         whitebtn.grid(row=0, column=2, rowspan=2, sticky=E, padx=padx)
       
   395 
       
   396     def update_yourself(self, red, green, blue):
       
   397         self.__reds.update_yourself(red, green, blue)
       
   398         self.__greens.update_yourself(red, green, blue)
       
   399         self.__blues.update_yourself(red, green, blue)
       
   400 
       
   401     def __togglehex(self, event=None):
       
   402         red, green, blue = self.__sb.current_rgb()
       
   403         self.update_yourself(red, green, blue)
       
   404 
       
   405 ##    def __togglegentype(self, event=None):
       
   406 ##        which = self.__gentypevar.get()
       
   407 ##        if which == 0:
       
   408 ##            self.__reds.set(label='Red Variations',
       
   409 ##                            generator=constant_cyan_generator)
       
   410 ##            self.__greens.set(label='Green Variations',
       
   411 ##                              generator=constant_magenta_generator)
       
   412 ##            self.__blues.set(label='Blue Variations',
       
   413 ##                             generator=constant_yellow_generator)
       
   414 ##        elif which == 1:
       
   415 ##            self.__reds.set(label='Red Constant',
       
   416 ##                            generator=constant_red_generator)
       
   417 ##            self.__greens.set(label='Green Constant',
       
   418 ##                              generator=constant_green_generator)
       
   419 ##            self.__blues.set(label='Blue Constant',
       
   420 ##                             generator=constant_blue_generator)
       
   421 ##        else:
       
   422 ##            assert 0
       
   423 ##        self.__sb.update_views_current()
       
   424 
       
   425     def __toblack(self, event=None):
       
   426         self.__sb.update_views(0, 0, 0)
       
   427 
       
   428     def __towhite(self, event=None):
       
   429         self.__sb.update_views(255, 255, 255)
       
   430 
       
   431     def save_options(self, optiondb):
       
   432         optiondb['UPWHILEDRAG'] = self.__uwdvar.get()
       
   433         optiondb['HEXSTRIP'] = self.__hexpvar.get()