## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by

#############################################################################
#
# Author: <NAME>
#
# Copyright: <NAME> TSRI 2000
#
# Revision: <NAME>
#
#############################################################################
#
# $Header$
#
# $Id$
#

import types, numpy.oldnumeric as Numeric, os, sys
import tkinter, Pmw
import tkinter.filedialog

# from string import strip, split, find

from opengltk.OpenGL import GL
from opengltk.extent import _gllib as gllib
from mglutil.util.misc import deepCopySeq
from mglutil.gui.BasicWidgets.Tk.thumbwheel import ThumbWheel
from mglutil.util.colorUtil import (
    HSL2RGB,
    RGB2HSL,
    RGBA2HSLA_list,
    HSLA2RGBA_list,
    ToHSV,
    ToHEX,
)
from mglutil.gui import widgetsOnBackWindowsCanGrabFocus

from DejaVu import viewerConst
from DejaVu.colorMap import ColorMap
from DejaVu.MaterialEditor import OGLWidget
from DejaVu.colorMapLegend import ColorMapLegend
from DejaVu.Geom import Geom
from DejaVu.colorTool import (
    RGBARamp,
    RedWhiteBlueRamp,
    RedWhiteRamp,
    WhiteBlueRamp,
    TkColor,
)
from DejaVu.Legend import drawLegendOnly


class ComboBoxRename(Pmw.ComboBox):
    def setExternalList(self, externalList, reverse=False, numOfBlockedLabels=0):
        self.externalList = externalList
        self.reverse = reverse
        self.numOfBlockedLabels = numOfBlockedLabels

    def _addHistory(self):
        # print "_addHistory"
        lCurSelection = self.curselection()
        if len(lCurSelection) > 0:
            lCurSelection0 = int(lCurSelection[0])
            if self.reverse is True:
                lBoolTest = (
                    len(self.externalList) - 1 - lCurSelection0
                ) >= self.numOfBlockedLabels
            else:
                lBoolTest = lCurSelection0 >= self.numOfBlockedLabels
            if lBoolTest:
                input = self._entryWidget.get()
                if (input != "") and (input not in self._list.get(0, "end")):
                    self.delete(lCurSelection0)
                    self.insert(lCurSelection0, input)
                    if self.reverse is True:
                        self.externalList[
                            len(self.externalList) - 1 - lCurSelection0
                        ] = input
                    else:
                        self.externalList[lCurSelection0] = input
            self.selectitem(lCurSelection0)
        else:
            self.selectitem(0)


class DummyEvent:
    """dummy Tkinter event """

    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y


COLORMAPGUI_MAXIMAL_HEIGHT = 1024


class ColorMapGUI(tkinter.Frame, ColorMap):
    """The ColorMapGUI is an object providing an interface to expose
    and to modify a ColorMap object.

    The ColorMapGUI has a local copy of the colormap.ramp, colormap.mini and
    colormap.maxi which will be modified through the GUI.
    The associated colormap object will only be updated when by the apply_cb
    which is called whenever a mouseUp event or update is called if the gui
    is in continuous mode or when the Aplly button is pressed when the gui is
    not in a continuous mode.

    The GUI allows the user to edit each of 4 different color
    properties: 'Hue','Sat' or saturation, 'Val' or value
    and 'Opa' or opacity for each entry in the ramp of the
    ColorMap. This is implemented via 4 Canvases, one for
    each color property. (Drawing on a canvas is done by
    pressing the left mouse button over the canvas and
    holding it down while moving the mouse.)
    Drawing at a point 'x','y', on one of the canvases changes
    the value of the corresponding color property in this way:
    'y' specifies the entry in the ColorMap.ramp to be changed.
    'x' is first normalized to give a value between 0 and 1.0.
    (by dividing it by the effective canvas width).
    A new rgba value is built from the hsva list comprised of
    3 previous values and this new normalized 'x' in the
    appropriate position. (that is, if the user is drawing on
    the 'Hue' canvas, the normalized 'x' value replaces the 'h',
    or zeroth entry,etc).

    If the GUI has a viewer, an OpenGLColorMapWidget is constructed
    which displays the GUI's current rgbMap. Also, the user can choose
    to add a ColorMapLegend to the viewer which displays the current
    ColorMap.ramp and which can be labeled."""

    staticRamp = RGBARamp(size=128, upperValue=0.85).tolist()

    def __init__(
        self,
        cmap=None,
        master=None,
        continuous=0,
        allowRename=True,
        modifyMinMax=False,
        viewer=None,
        xoffset=25,
        width=200,
        height=256,
        geoms=None,
        name=None,
        ramp=None,
        labels=None,
        mini=None,
        maxi=None,
        filename=None,
        show=True,
        numOfBlockedLabels=0,
        **kw
    ):

        # this is the active colormap
        if cmap is None:
            ColorMap.__init__(
                self,
                name=name,
                ramp=ramp,
                labels=labels,
                filename=filename,
                mini=mini,
                maxi=maxi,
            )
        else:
            ColorMap.__init__(
                self,
                name=cmap.name,
                ramp=cmap.ramp,
                labels=cmap.labels,
                mini=cmap.mini,
                maxi=cmap.maxi,
            )

        self.history = []
        self.legend = None
        if geoms is None:
            geoms = {}
        self.geoms = geoms
        self.viewer = None
        self.currentOnStack = False
        self.numOfBlockedLabels = numOfBlockedLabels

        # initialize a bunch of flags.
        self.cmapCurrent = True
        self.cmapCompToReset = None
        self.cmapResetAll = False
        self.nbStepBack = 0

        # Initialize the local guiRamp, guiMini and guiMaxi values
        # which will be modified
        self.guiRamp = []
        self.guiMini = None
        self.guiMaxi = None
        if self.labels is not None:
            self.guiLabels = deepCopySeq(self.labels)
        self.colorbin = []
        self.labelbin = []
        self.lengthRamp = len(self.ramp)

        if height < self.lengthRamp:
            height = self.lengthRamp

        self.height = height
        self.linesPerRampValue = self.height / float(self.lengthRamp)
        self.currentHue = []
        self.currentSat = []

        # Create parts of the GUI
        if master is None:
            if viewer:
                theMaster = tkinter.Toplevel(viewer.master)
            else:
                theMaster = tkinter.Toplevel()
        else:
            theMaster = master

        if hasattr(theMaster, "protocol"):
            theMaster.protocol("WM_DELETE_WINDOW", self.dismiss)

        # we hide it if it was asked
        if show is False:
            master2 = theMaster
            while (
                hasattr(master2, "withdraw") is False
                and hasattr(master2, "master") is True
            ):
                master2 = master2.master
            master2.withdraw()

        tkinter.Frame.__init__(self, theMaster)
        tkinter.Pack.config(self, expand=1, fill="both")
        if hasattr(theMaster, "title"):
            theMaster.title(self.name)
        # Canvas width (default=200)
        self.width = width

        self.canvasStart = 4

        # left border width (default=25)
        self.xoffset = xoffset
        # Available drawing width default=width-xoffset
        self.xrange = float(width - xoffset)

        # DejaVu viewer to which colorMapLegend is added
        self.viewer = None

        self.continuousUpdate = tkinter.IntVar()
        self.continuousUpdate.set(continuous)

        # if allowRename is False, name entry is disabled.
        self.allowRename = allowRename
        self.modifyMinMax = modifyMinMax

        self.idList = ["Hue", "Sat", "Val", "Opa"]
        self.getColorFunc = {
            "Hue": self.hueColor,
            "Sat": self.satColor,
            "Val": self.valColor,
            "Opa": self.opaColor,
        }

        # initialize dictionaries
        # NB all the lines end at xpoints corresponding to the
        # the colorproperty value at that point... (except
        #'Hue' is backwards, width-property+xoffset instead of
        # property+xoffset)

        self.rightXVals = {}
        self.lines = {}
        for idStr in self.idList:
            self.rightXVals[idStr] = []
            self.lines[idStr] = []

        self.current = "Hue"  # name of the currently visible prop. canvas
        self.callbacks = []  # list of functions to be called when apply
        # button is pressed or ramp is modified and
        # mode is continuous update

        # Calls the createWidgets method to create the 4 canvases
        # and the buttons.
        self.createWidgets(theMaster)
        self.configureGui(
            ramp=self.ramp,
            geoms=self.geoms,
            legend=self.legend,
            labels=self.labels,
            mini=self.mini,
            maxi=self.maxi,
            **kw
        )

        # Call the update to initialize the gui with the given cmap values,
        # without configuring the cmap
        self.update(
            mini=self.mini, maxi=self.maxi, ramp=deepCopySeq(self.ramp), cfgCmap=False
        )
        self.cmapCurrent = True

        # set current colorFunc, lines and values to 'Hue'
        self.getColor = self.getColorFunc["Hue"]
        self.currentLines = self.lines["Hue"]
        self.currentValues = self.rightXVals["Hue"]

        tkinter.Widget.bind(self, "<Enter>", self.enter_cb)
        tkinter.Widget.bind(self, "<Leave>", self.leave_cb)

        # set-up canvas mouse bindings:
        for idStr in ["Hue", "Sat", "Val", "Opa"]:
            tkinter.Widget.bind(self.canvas[idStr], "<ButtonPress-1>", self.mouseDown)
            tkinter.Widget.bind(
                self.canvas[idStr], "<Button1-Motion>", self.mouseMotion
            )
            tkinter.Widget.bind(self.canvas[idStr], "<ButtonRelease-1>", self.mouseUp)

            tkinter.Widget.bind(self.canvas[idStr], "<Motion>", self.updateCurTk)

            tkinter.Widget.bind(
                self.canvas[idStr], "<ButtonPress-3>", self.mouseDownRight
            )
            tkinter.Widget.bind(
                self.canvas[idStr], "<Button3-Motion>", self.mouseMotionRight
            )
            tkinter.Widget.bind(
                self.canvas[idStr], "<ButtonRelease-3>", self.mouseUpRight
            )

            self.canvas[idStr].configure(cursor="cross")

        self.straightLine = None

        # create the cml
        if self.legend is None:
            self.createCML()

        self.SetViewer(viewer)

        #        # fields created by the CMLwidget
        #        self.legend.createOwnGui()
        #        self.legend.hideOwnGui()

        if master is not None:
            master2 = theMaster
            if hasattr(master2, "master") is True and isinstance(
                master2.master, tkinter.Widget
            ):
                master2 = master2.master
            if hasattr(master2, "master") is True and isinstance(
                master2.master, tkinter.Widget
            ):
                master2 = master2.master
            # Tkinter.Widget.bind(master2, '<Configure>', self.configure_cb)
            self.inVision = True
        else:
            tkinter.Widget.bind(self.fullWidgetFrame, "<Configure>", self.configure_cb)
            self.inVision = False

    def configure_cb(self, event=None):
        # print "configure_cb", event, dir (event)
        # print "configure_cb event.height", event.height

        #        self.width = event.width
        #        self.xrange = float(self.width - self.xoffset)

        if self.inVision is True:
            height = (
                event.height
                - 2 * self.canvasStart
                - self.menuFrame1.winfo_reqheight()
                - self.buttonFrame.winfo_reqheight()
                - 73
            )
        elif os.name == "nt":  # sys.platform == 'win32':
            height = (
                event.height
                - 2 * self.canvasStart
                - self.menuFrame1.winfo_reqheight()
                - self.buttonFrame.winfo_reqheight()
                - self.frame2.winfo_reqheight()
                - 2
            )
        else:
            height = (
                event.height
                - 2 * self.canvasStart
                - self.menuFrame1.winfo_reqheight()
                - self.buttonFrame.winfo_reqheight()
                - self.frame2.winfo_reqheight()
            )

        # print "configure_cb height", height
        if height >= self.lengthRamp and height > 0:
            self.height = height
            # print "self.height 1", self.height
            self.linesPerRampValue = self.height / float(self.lengthRamp)
            self.resizeCanvases(self.height)
            self.drawRampCanvases(drawRamp=True)

    def changeRampLength_cb(self, numOfRampValue):
        # print "changeRampLength_cb", numOfRampValue, len(self.guiRamp), len(self.ramp)
        # import traceback;traceback.print_stack()

        lenguiramp = len(self.guiRamp)
        if numOfRampValue < self.numOfBlockedLabels:
            self.numOfRampValues.set(lenguiramp)
            return
        elif numOfRampValue == lenguiramp:
            return
        elif numOfRampValue < lenguiramp:
            for i in range(numOfRampValue, lenguiramp):
                self.colorbin.append(self.guiRamp.pop())
        else:  # numOfRampValue > lenguiramp:
            lNumOfColorsToAdd = numOfRampValue - lenguiramp
            lNumOfColorsToCreate = lNumOfColorsToAdd - len(self.colorbin)
            if lNumOfColorsToCreate > 0:
                for i in range(len(self.colorbin)):
                    self.guiRamp.append(self.colorbin.pop())
                for i in range(lNumOfColorsToCreate):
                    lIndex = len(self.guiRamp) % len(self.staticRamp)
                    self.guiRamp.append(self.staticRamp[lIndex])
            else:
                for i in range(lNumOfColorsToAdd):
                    self.guiRamp.append(self.colorbin.pop())

        self.configureGui(
            ramp=self.guiRamp,
            mini=self.mini,
            maxi=self.maxi,
            updateGui=True,
            theGivenRampIsTheGuiRamp=True,
            # guiRamp=self.guiRamp
        )
        self.cmapCurrent = False

    def adjustGuiLabels(self, newNumOfGuiLabels):
        # print "adjustGuiLabels", newNumOfGuiLabels

        lenguiLabels = len(self.guiLabels)
        if newNumOfGuiLabels == lenguiLabels:
            return
        elif newNumOfGuiLabels < lenguiLabels:
            for i in range(newNumOfGuiLabels, lenguiLabels):
                self.labelbin.append(self.guiLabels.pop())
        else:
            lNumOfLabelsToAdd = newNumOfGuiLabels - lenguiLabels
            lNumOfLabelsToCreate = lNumOfLabelsToAdd - len(self.labelbin)
            if lNumOfLabelsToCreate > 0:
                for i in range(len(self.labelbin)):
                    self.guiLabels.append(self.labelbin.pop())
                for i in range(lNumOfLabelsToCreate):
                    self.guiLabels.append(str(len(self.guiLabels)))
            else:
                for i in range(lNumOfLabelsToAdd):
                    self.guiLabels.append(self.labelbin.pop())
        self.configureGui(labels=self.guiLabels)

    def createCML(self):
        """create the ColorMap Legend"""
        if self.legend:
            return
        # width defaults to len(ramp); height defaults to 1
        # mini, maxi and interp set from self
        cmlOptions = {"width": 10, "height": 1, "name": self.name, "ramp": self.ramp}

        if self.mini is not None:
            cmlOptions["mini"] = self.mini

        if self.maxi is not None:
            cmlOptions["maxi"] = self.maxi

        self.legend = ColorMapLegend(*(self,), **cmlOptions)

    #    def resetComp(self, comp):
    #        """resets on component to first entry in history list"""
    #        compNum = ['Hue','Sat','Val','Opa'].index(comp)
    #        # Get the first entry in the history list
    #        hist = self.history[0]
    #        # Remove all the entries in the history list
    #        self.history = self.history[:1]
    #
    #        # Transform the history RGBramp into a HSL ramp
    #        histHSL = map(lambda x: list(RGBA2HSLA_list(x)), hist)
    #        # Transform the current ramp in a HSL ramp
    #        hsl = map(lambda x: list(x), self.asHSL())
    #        for i in range(len(hsl)):
    #            hsl[i][compNum] = histHSL[i][compNum]
    #        ramp = map(lambda x: list(HSLA2RGBA_list(x)), hsl)
    #        self.configure(ramp=ramp, updateGui=False)

    def reset(self):
        """return to first entry in history list"""
        ramp = self.history[0]
        self.history = []
        self.configure(ramp=deepCopySeq(ramp), updateGui=False)

    def pushRamp(self):
        """
        The pushRamp method appends the current ramp stored in cmap.ramp at the
        end of the history list.
        The attribute self.currentOnStack is set to True.
        """
        # append the current ramp to the history if the ramp is not None and
        # if the ramp has not been pushed onto the history stack yet.
        if self.ramp is None or self.currentOnStack:
            return
        self.history.append(deepCopySeq(self.ramp))
        self.currentOnStack = True

    def popRamp(self, index=-1):
        """
        optional arguments
        index -- default -1, specifies the index of the ramp to pop.
                 It is a negative index
                 as we are popping ramps from the end of the history list.

        The popRamp method will save the ramp stored at the given index
        in cmap.ramp then remove all the entry from the ramp (included)
        till the end of the history list.
        After a popRamp the attribute self.currentOnStack is False.
        """
        # Need at least one entry in the history
        if not len(self.history):
            return

        # Always keep the first entry of the history
        if len(self.history) == 1:
            if not self.currentOnStack:
                self.ramp = self.history[0]
                self.currentOnStack = True
            return
        # PopRamp removes entry from the end of the history list
        # which is why the index has to be negative.
        assert index < 0

        # 1- set the actual ramp to be the entry of history
        # corresponding to the given index
        # 2- history = history[:index]
        # the popped history is not on the stack any longer except
        # when it is the first entry

        # Get the index from the beginning of the history list
        newind = len(self.history) + index
        pushRamp = False
        if newind <= 0:
            newind = 0
            # Always keep the first entry in the history list
            pushRamp = True

        elif newind >= len(self.history):
            newind = -1
            pushRamp = False

        ramp = self.history[newind]
        self.history = self.history[:newind]
        # We do not want to push the ramp we are popping onto the history stack
        # the current ramp will not be on the history stack any longer.
        self.configure(ramp=deepCopySeq(ramp), updateGui=False, pushRamp=pushRamp)

    def SetViewer(self, viewer):
        """to give a viewer reference to the ColorMapGUI even
        after it's creation"""
        if viewer:
            if self.viewer is not None:

                self.viewer.RemoveObject(self.legend)

            self.viewer = viewer
            self.createCML()

            self.legend.name = self.viewer.ensureUniqueName(self.legend.name)
            self.update(cmapName=self.legend.name)

            self.legend.replace = False
            # self.legend.protected = True
            self.viewer.AddObject(self.legend, redo=0)

            self.showLegendVar = tkinter.IntVar()
            self.showLegendButton = tkinter.Checkbutton(
                self.buttonFrame,
                text="show legend",
                variable=self.showLegendVar,
                command=self.showLegendButton_cb,
            )
            self.showLegendButton.grid(row=5, column=0, columnspan=2, sticky="w")

    def createWidgets(self, master):
        """create Tkinter widgets: 4 canvas and buttons in 2 frames"""
        # print "createWidgets"
        self.fullWidgetFrame = tkinter.Frame(master)
        self.fullWidgetFrame.pack(side="top", expand=1, fill="both")

        # create menu frame
        self.menuFrame1 = tkinter.Frame(
            self.fullWidgetFrame, relief="raised", borderwidth=3
        )
        self.menuFrame1.pack(side="top", expand=1, fill="x")

        filebutton = tkinter.Menubutton(self.menuFrame1, text="File")
        filebutton.pack(side="left")
        filemenu = tkinter.Menu(filebutton, {})
        filemenu.add_command(label="Read", command=self.read_cb)
        filemenu.add_command(label="Write", command=self.write_cb)
        filebutton["menu"] = filemenu

        editbutton = tkinter.Menubutton(self.menuFrame1, text="Edit")
        editbutton.pack(side="left", anchor="w")
        editmenu = tkinter.Menu(editbutton, {})
        editmenu.add_command(
            label="Reset to first in history", command=self.resetAll_cb
        )
        editmenu.add_command(
            label="Step back in history loop", command=self.stepBack_cb
        )
        ##         editmenu.add_checkbutton(label='Preview', variable=self.preview)
        editmenu.add_checkbutton(label="Continuous", variable=self.continuousUpdate)

        editmenu.add_command(label="Edit Legend", command=self.editLegend_cb)

        editbutton["menu"] = editmenu

        self.numOfRampValues = ThumbWheel(
            self.menuFrame1,
            labCfg={"text": "Num of colors:", "side": "left"},
            showLabel=1,
            width=80,
            height=16,
            min=1,
            max=COLORMAPGUI_MAXIMAL_HEIGHT,
            type=int,
            value=self.lengthRamp,
            callback=self.changeRampLength_cb,
            continuous=True,
            oneTurn=60,
            wheelPad=2,
        )
        self.numOfRampValues.pack(side="right", anchor="e")

        # create canvas frames
        self.canvasesFrame = tkinter.Frame(self.fullWidgetFrame)

        # create a frame for rproperties canvases
        self.propCanvasFrame = tkinter.Frame(self.canvasesFrame)

        # create 4 canvases
        self.canvas = {}
        for idStr in self.idList:
            self.canvas[idStr] = tkinter.Canvas(
                self.propCanvasFrame,
                relief="sunken",
                borderwidth=3,
                width=self.width,
                height=self.height,
            )
        # pack Hue to start with
        self.canvas["Hue"].pack(side="left", expand=1, fill="both")
        self.propCanvasFrame.pack(side="left", expand=1, fill="both")

        self.ogl_cmw = OGLColorMapWidget(
            self.canvasesFrame,
            self,
            width=19,
            height=self.height,
        )

        self.canvasesFrame.pack(side="top", expand=1, fill="both")

        # create a frame for buttons
        self.buttonFrame = tkinter.Frame(
            self.fullWidgetFrame, relief="ridge", borderwidth=3
        )

        # create radio buttons to switch between canvas
        self.currentCanvasVar = tkinter.StringVar()
        self.buttonHue = tkinter.Radiobutton(
            self.buttonFrame,
            text="Hue",
            value="Hue",
            width=8,
            indicatoron=0,
            variable=self.currentCanvasVar,
            command=self.button_cb,
        )
        self.buttonHue.grid(row=0, column=0, sticky="we")  # pack(side='left')

        self.buttonSat = tkinter.Radiobutton(
            self.buttonFrame,
            text="Sat.",
            value="Sat",
            width=8,
            indicatoron=0,
            variable=self.currentCanvasVar,
            command=self.button_cb,
        )
        self.buttonSat.grid(row=0, column=1, sticky="we")  # pack(side='left')

        self.buttonVal = tkinter.Radiobutton(
            self.buttonFrame,
            text="Lum.",
            value="Val",
            width=8,
            indicatoron=0,
            variable=self.currentCanvasVar,
            command=self.button_cb,
        )
        self.buttonVal.grid(row=0, column=2, sticky="we")  # pack(side='left')

        self.buttonOpa = tkinter.Radiobutton(
            self.buttonFrame,
            text="Opa.",
            value="Opa",
            width=8,
            indicatoron=0,
            variable=self.currentCanvasVar,
            command=self.button_cb,
        )
        self.buttonOpa.grid(row=0, column=3, sticky="we")  # pack(side='left')

        self.currentCanvas = self.canvas["Hue"]
        self.currentCanvasVar.set("Hue")

        # name
        self.nameVar = tkinter.StringVar()
        if self.name is not None:
            self.nameVar.set(self.name)
        a = tkinter.Label(self.buttonFrame, text="name")
        a.grid(row=2, column=0, sticky="e")
        if self.allowRename is True:
            self.nameEntry = tkinter.Entry(
                self.buttonFrame, textvariable=self.nameVar, width=18
            )
            self.nameEntry.bind("<Return>", self.rename_cb)
            self.nameEntry.bind("<Leave>", self.rename_cb)
        else:
            self.nameEntry = tkinter.Label(
                self.buttonFrame,
                textvariable=self.nameVar,
                width=18,
                relief="groove",
                padx=2,
                pady=1,
            )
        self.nameEntry.grid(row=2, column=1, columnspan=3, sticky="w")

        # min max
        self.maxTk = tkinter.StringVar()
        if self.guiMaxi is not None:
            self.maxTk.set(("%8.2f" % self.guiMaxi))
        a = tkinter.Label(self.buttonFrame, text="max")
        a.grid(row=3, column=2, sticky="e")
        if self.modifyMinMax:
            self.maxEntry = tkinter.Entry(
                self.buttonFrame, textvariable=self.maxTk, width=8
            )
            self.maxEntry.bind("<Return>", self.max_cb)
            self.maxEntry.bind("<Leave>", self.max_cb)
        else:
            self.maxEntry = tkinter.Label(
                self.buttonFrame,
                textvariable=self.maxTk,
                width=8,
                relief="groove",
                justify="left",
                padx=2,
                pady=1,
            )
        self.maxEntry.grid(row=3, column=3, sticky="w")

        self.curyTk = tkinter.StringVar()
        a = tkinter.Label(self.buttonFrame, text="y ")
        a.grid(row=4, column=2, sticky="e")
        self.curYLabel = tkinter.Label(
            self.buttonFrame,
            textvariable=self.curyTk,
            width=8,
            relief="groove",
            justify="left",
            padx=2,
            pady=1,
        )
        self.curYLabel.grid(row=4, column=3, sticky="w")

        self.minTk = tkinter.StringVar()
        if self.guiMini is not None:
            self.minTk.set(("%8.2f" % self.guiMini))
        a = tkinter.Label(self.buttonFrame, text="min")
        a.grid(row=5, column=2, sticky="e")
        if self.modifyMinMax:
            self.minEntry = tkinter.Entry(
                self.buttonFrame, textvariable=self.minTk, width=8
            )
            self.minEntry.bind("<Return>", self.min_cb)
            self.minEntry.bind("<Leave>", self.min_cb)
        else:
            self.minEntry = tkinter.Label(
                self.buttonFrame,
                textvariable=self.minTk,
                width=8,
                relief="groove",
                justify="right",
                padx=2,
                pady=1,
            )
        self.minEntry.grid(row=5, column=3, sticky="w")

        self.curxTk = tkinter.StringVar()
        a = tkinter.Label(self.buttonFrame, text="x")
        a.grid(row=4, column=1, sticky="w")
        self.curXLabel = tkinter.Label(
            self.buttonFrame,
            textvariable=self.curxTk,
            width=8,
            relief="groove",
            justify="left",
            padx=2,
            pady=1,
        )
        self.curXLabel.grid(row=4, column=0, sticky="w")

        if self.labels is not None:
            # self.labelsInComboBox = Tkinter.StringVar()
            self.labelsComboBox = ComboBoxRename(
                self.buttonFrame, label_text="label", labelpos="w", history=1
            )
            self.labelsComboBox.setExternalList(
                self.guiLabels, reverse=True, numOfBlockedLabels=self.numOfBlockedLabels
            )
            self.labelsComboBox.grid(row=6, column=0, columnspan=4, sticky="w")

        # Apply and Dismiss go here
        self.frame2 = tkinter.Frame(self.fullWidgetFrame, relief="raise", borderwidth=3)
        f2 = self.frame2
        self.apply = tkinter.Button(f2, text="Apply", command=self.apply_cb)
        self.apply.pack(side="left", expand=1, fill="x")
        self.dismiss = tkinter.Button(f2, text="Dismiss", command=self.dismiss)
        self.dismiss.pack(side="left", expand=1, fill="x")

        f2.pack(side="bottom", expand=1, fill="x")
        self.frame2.pack(side="bottom", expand=1, fill=tkinter.X)
        self.buttonFrame.pack(side="bottom", expand=1, fill="x")

    def update(
        self,
        ramp=None,
        mini=None,
        maxi=None,
        cmapName=None,
        drawRamp=True,
        cfgCmap=True,
        theGivenRampIsTheGuiRamp=False,
        # guiRamp=None
    ):

        # Update the name of cmg if relevant
        if hasattr(self.master, "title"):
            self.master.title(cmapName)

        # Update the maxi and mini values of cmg
        if maxi is not None and mini is not None:
            if mini <= maxi:
                self.guiMaxi = maxi
                self.guiMini = mini
                self.minTk.set(("%8.2f" % self.guiMini))
                self.maxTk.set(("%8.2f" % self.guiMaxi))
            else:
                self.guiMaxi = None
                self.guiMini = None
                self.minTk.set("")
                self.maxTk.set("")
        elif maxi is not None and mini is None:
            if self.guiMini <= maxi:
                self.guiMaxi = maxi
                self.maxTk.set(("%8.2f" % self.guiMaxi))
            else:
                self.guiMaxi = None
                self.maxTk.set("")
        elif mini is not None and maxi is None:
            if mini <= self.guiMaxi:
                self.guiMini = mini
                self.minTk.set(("%8.2f" % self.guiMini))
            else:
                self.guiMini = None
                self.minTk.set("")

        # Update the cmg ramp with the one given
        if not ramp is None:
            if theGivenRampIsTheGuiRamp is False:
                self.cmapCurrent = False
                ramp = deepCopySeq(self.checkRamp(ramp))
                self.lengthRamp = len(ramp)
                if self.lengthRamp > self.height:
                    self.height = self.lengthRamp
                    # print "self.height 2", self.height
                self.numOfRampValues.set(self.lengthRamp)
                self.linesPerRampValue = self.height / float(self.lengthRamp)
                self.resizeCanvases(self.height)
                self.guiRamp = ramp
                if self.labels is not None:
                    self.adjustGuiLabels(self.lengthRamp)
                self.drawRampCanvases(drawRamp=drawRamp)
            else:
                # print "guiRamp"
                self.lengthRamp = len(ramp)
                if self.lengthRamp > self.height:
                    self.height = self.lengthRamp
                    # print "self.height 3", self.height
                # self.numOfRampValues.set(self.lengthRamp)
                self.linesPerRampValue = self.height / float(self.lengthRamp)
                self.resizeCanvases(self.height)
                # self.guiRamp = guiRamp
                if self.labels is not None:
                    self.adjustGuiLabels(self.lengthRamp)
                self.drawRampCanvases(drawRamp=drawRamp)

        # Update the OpenGL ramp
        self.ogl_cmw.ramp = deepCopySeq(self.guiRamp)
        self.ogl_cmw.tkRedraw()

        if self.continuousUpdate.get():
            self.configureCmap(cfgCmap=cfgCmap)

    def configure(
        self,
        name=None,
        ramp=None,
        geoms=None,
        legend=None,
        labels=None,
        mini="not passed",
        maxi="not passed",
        viewer=None,
        updateGui=True,
        pushRamp=True,
        **kw
    ):
        # print "ColorMapGUI.configure", mini, maxi
        ColorMap.configure(
            self, name=name, ramp=ramp, labels=labels, mini=mini, maxi=maxi
        )

        if ramp is not None:
            ramp = self.ramp
        if labels is not None:
            labels = self.labels  # because it was just set in the configure

        self.configureGui(
            ramp=ramp,
            labels=labels,
            geoms=geoms,
            legend=legend,
            viewer=viewer,
            updateGui=updateGui,
            pushRamp=pushRamp,
            **kw
        )

    def configureGui(
        self,
        name=None,
        ramp=None,
        labels=None,
        geoms=None,
        legend=None,
        viewer=None,
        updateGui=True,
        pushRamp=True,
        # guiRamp=None,
        theGivenRampIsTheGuiRamp=False,
        **kw
    ):
        """Configure the colormapGui with the given values."""
        if (ramp is not None) and (theGivenRampIsTheGuiRamp is False):
            # The ramp is new put has not been pushed onto the history
            # stack yet
            self.currentOnStack = False
            # When pushRamp is True this new ramp is pushed on the stack
            if pushRamp:
                self.pushRamp()

        if labels is not None and self.labels is not None:
            # print "labels", labels
            # import traceback;traceback.print_stack()
            self.labelsComboBox.delete(0, "end")
            for label in labels:
                self.labelsComboBox.insert(0, str(label))

        if geoms is not None and len(geoms):
            self.geoms.update(geoms)
        if viewer is not None and viewer != self.viewer:
            self.SetViewer(viewer)
            if self.name != self.legend.name:
                self.nameVar.set(self.legend.name)
                self.rename_cb()
        # if a legend is specified then set self.legend
        if legend is not None:
            self.legend = legend

        # Then update the legend with the given values
        if self.legend is not None:
            cmlOptions = {"ramp": self.ramp}

            # Need to update the legendValues as well
            cmlOptions["mini"] = self.mini
            cmlOptions["maxi"] = self.maxi

            if hasattr(self, "showLegendVar"):
                cmlOptions["visible"] = self.showLegendVar.get()
            self.legend.Set(*(), **cmlOptions)

        if updateGui:
            self.update(
                ramp=ramp,
                mini=self.mini,
                maxi=self.maxi,
                cfgCmap=False,
                theGivenRampIsTheGuiRamp=theGivenRampIsTheGuiRamp,
            )

    def Map(self, values, mini="not passed", maxi="not passed"):

        col = ColorMap.Map(self, values, mini=mini, maxi=maxi)

        if self.legend is not None:
            cmlOptions = {"ramp": self.ramp}

            # Need to update the legendValues with the value that where just used
            cmlOptions["mini"] = self.lastMini
            cmlOptions["maxi"] = self.lastMaxi

            if hasattr(self, "showLegendVar"):
                cmlOptions["visible"] = self.showLegendVar.get()
            self.legend.Set(*(), **cmlOptions)

        return col

    def configureCmap(self, cfgCmap=True):
        """This method configures the associated cmap with the GUI new values."""
        if self.cmapCompToReset is not None:
            self.resetComp(self.cmapCompToReset)
            self.cmapCompToReset = None
            cfgCmap = False
            self.cmapCurrent = True

        if self.cmapResetAll is True:
            self.reset()
            self.cmapResetAll = False
            cfgCmap = False
            self.cmapCurrent = True

        if self.nbStepBack != 0:
            if self.nbStepBack == len(self.history):
                cfgCmap = False
                self.cmapCurrent = True
            self.popRamp(-self.nbStepBack)
            self.nbStepBack = 0

        if cfgCmap:
            #            if self.allowRename:
            #                name = self.nametk.get()
            #            else:
            #                name=None

            # donnot update the cmap if already current...
            if self.cmapCurrent:
                ramp = None
            else:
                ramp = deepCopySeq(self.guiRamp)
            self.configure(ramp=ramp, mini=self.guiMini, maxi=self.guiMaxi)

            if self.legend is not None:
                if self.legend.viewer:
                    self.tk.call(self.legend.viewer.currentCamera._w, "makecurrent")
                    self.legend.RedoDisplayList()
                    self.legend.viewer.Redraw()

            self.cmapCurrent = True

        if self.labels is not None:
            self.labels = deepCopySeq(self.guiLabels)
            # print "self.labels", self.labels

        # Then will call the callbacks with the new cmap values.
        self.callCallbacks()

    def drawRampCanvases(self, event=None, drawRamp=True):
        """draw all ramp canvases"""
        # print "drawRampCanvases"
        # update Ramp

        self.currentHue = list(range(self.lengthRamp))
        self.currentSat = list(range(self.lengthRamp))

        if drawRamp:
            for v in self.idList:
                self.deleteCanvasLines(v)
                self.setRightXVals(v)
            var = self.currentCanvasVar.get()
            self.currentValues = self.rightXVals[var]
            self.drawHue()
            self.drawSaturation()
            self.drawValue()
            self.drawOpacity()

    #################################################################
    ### MOUSE CALLBACKS
    #################################################################
    def mouseUp(self, event=None):
        self.cmapCurrent = False
        self.update(drawRamp=False)

    def mouseDown(self, event):
        j = self.canvasStart
        # canvas x and y take the screen coords from the event and translate
        # them into the coordinate system of the canvas object
        Y = min(j + self.height - 1, event.y)
        x = min(self.width, event.x)
        x = max(self.xoffset, x)
        if Y < j:
            Y = j
        y = int((Y - j) / self.linesPerRampValue)
        if y < 0:
            y = 0
        self.startx = x
        self.startY = Y
        self.starty = y
        self.updateCurTk(event)
        c = self.currentCanvas
        lineIndex = self.lengthRamp - 1 - y
        line = self.currentLines[lineIndex]
        col, graybitmap = self.getColor(x, lineIndex)  # y
        newline = c.create_rectangle(
            j,
            y * self.linesPerRampValue + j,
            1 + x,  # +j,
            (1 + y) * self.linesPerRampValue + j,
            outline="",
            fill=col,
            stipple=graybitmap,
        )
        self.currentLines[lineIndex] = newline
        # update self.guiRamp
        self.updateRGBMap(x, lineIndex)
        # update rightXVals
        self.currentValues[lineIndex] = x
        c.delete(line)

    def mouseMotion(self, event):
        j = self.canvasStart
        # canvas x and y take the screen coords from the event and translate
        # them into the coordinate system of the canvas object
        # x,y are float
        # x = self.canvasHue.canvasx(event.x)
        # y = self.canvasHue.canvasy(event.y)
        # event.x, event.y are same as x,y but int
        Y = min(j + self.height - 1, event.y)
        x = min(self.width, event.x)
        x = max(self.xoffset, x)
        if Y < j:
            Y = j
        y = int((Y - j) / self.linesPerRampValue)
        if y < 0:
            y = 0
        elif self.startx is None:
            self.mouseDown(event)
        c = self.currentCanvas
        if self.startY == Y:
            lineIndex = self.lengthRamp - 1 - y
            # print "lineIndex 0 ...", lineIndex
            line = self.currentLines[lineIndex]
            col, graybitmap = self.getColor(x, lineIndex)
            newline = c.create_rectangle(
                j,
                y * self.linesPerRampValue + j,
                1 + x,  # +j,
                (1 + y) * self.linesPerRampValue + j,
                outline="",
                fill=col,
                stipple=graybitmap,
            )
            self.currentLines[lineIndex] = newline
            c.delete(line)
            self.currentValues[lineIndex] = x
            self.updateRGBMap(x, lineIndex)
        else:  # we need to interpolate for all y's between self.starty and y
            dx = x - self.startx
            dy = Y - self.startY
            rat = float(dx) / float(dy)
            if Y > self.startY:
                for Yl in range(self.startY, Y + 1):
                    yl = int((Yl - j) / self.linesPerRampValue)
                    ddx = int(rat * (Yl - self.startY)) + self.startx
                    lineIndex = self.lengthRamp - 1 - yl
                    # print "lineIndex 1 ...", lineIndex
                    line = self.currentLines[lineIndex]
                    col, graybitmap = self.getColor(ddx, lineIndex)
                    newline = c.create_rectangle(
                        j,
                        yl * self.linesPerRampValue + j,
                        1 + ddx,  # +j,
                        (yl + 1) * self.linesPerRampValue + j,
                        outline="",
                        fill=col,
                        stipple=graybitmap,
                    )
                    self.currentLines[lineIndex] = newline
                    c.delete(line)
                    self.currentValues[lineIndex] = ddx
                    self.updateRGBMap(ddx, lineIndex)
            else:
                for Yl in range(self.startY, Y - 1, -1):
                    yl = int((Yl - j) / self.linesPerRampValue)
                    ddx = int(rat * (Yl - self.startY)) + self.startx
                    lineIndex = self.lengthRamp - 1 - yl
                    # print "lineIndex 2 ...", lineIndex
                    line = self.currentLines[lineIndex]
                    col, graybitmap = self.getColor(ddx, lineIndex)
                    newline = c.create_rectangle(
                        j,
                        yl * self.linesPerRampValue + j,
                        1 + ddx,  # +j,
                        (1 + yl) * self.linesPerRampValue + j,
                        outline="",
                        fill=col,
                        stipple=graybitmap,
                    )
                    self.currentLines[lineIndex] = newline
                    c.delete(line)
                    self.currentValues[lineIndex] = ddx
                    self.updateRGBMap(ddx, lineIndex)
            self.startY = Y
            self.startx = x
            # this flushes the output, making sure that
            # the rectangle makes it to the screen
            # before the next event is handled
        self.update_idletasks()
        self.updateCurTk(event)

    def mouseDownRight(self, event):
        j = self.canvasStart
        Y = min(j + self.height - 1, event.y)
        x = min(self.width, event.x)
        x = max(self.xoffset, x)
        if Y < j:
            Y = j
        y = int((Y - j) / self.linesPerRampValue)
        if y < 0:
            y = 0
        self.startx = x
        self.startY = Y
        self.starty = y

    def mouseMotionRight(self, event):
        j = self.canvasStart
        Y = min(j + self.height - 1, event.y)
        x = min(self.width, event.x)
        x = max(self.xoffset, x)
        if Y < j:
            Y = j
        y = int((Y - j) / self.linesPerRampValue)
        if y < 0:
            y = 0
        elif self.startx is None:
            self.mouseDown(event)
        c = self.currentCanvas
        if self.straightLine is not None:
            c.delete(self.straightLine[0])
            c.delete(self.straightLine[1])

        dy = Y - self.startY
        if abs(dy) < (self.linesPerRampValue / 2):
            return

        straightLineBlack = c.create_line(
            self.startx,  # +j,
            (self.starty + 0.5) * self.linesPerRampValue + j,
            x,  # +j,
            (y + 0.5) * self.linesPerRampValue + j,
            fill="black",
            width=3,
        )
        straightLineWhite = c.create_line(
            self.startx,  # +j,
            (self.starty + 0.5) * self.linesPerRampValue + j,
            x,  # +j,
            (y + 0.5) * self.linesPerRampValue + j,
            fill="white",
            width=1,
        )
        self.straightLine = [straightLineBlack, straightLineWhite]
        self.update_idletasks()
        self.updateCurTk(event)

    def mouseUpRight(self, event=None):
        j = self.canvasStart
        c = self.currentCanvas
        if self.straightLine is not None:
            c.delete(self.straightLine[0])
            c.delete(self.straightLine[1])
        Y = min(j + self.height - 1, event.y)
        x = min(self.width, event.x)
        x = max(self.xoffset, x)
        if Y < j:
            Y = j
        y = int((Y - j) / self.linesPerRampValue)
        if y < 0:
            y = 0
        elif self.startx is None:
            self.mouseDown(event)
        dx = x - self.startx
        dY = Y - self.startY
        dy = y - self.starty
        if abs(dY) < (self.linesPerRampValue / 2):
            return
        rat = float(dx) / float(dy)
        if y > self.starty:
            for yl in range(self.starty, y + 1):
                ddx = int(rat * (yl - self.starty)) + self.startx
                lineIndex = self.lengthRamp - 1 - yl
                line = self.currentLines[lineIndex]
                col, graybitmap = self.getColor(ddx, lineIndex)
                newline = c.create_rectangle(
                    j,
                    yl * self.linesPerRampValue + j,
                    1 + ddx,  # +j,
                    (yl + 1) * self.linesPerRampValue + j,
                    outline="",
                    fill=col,
                    stipple=graybitmap,
                )
                self.currentLines[lineIndex] = newline
                c.delete(line)
                self.currentValues[lineIndex] = ddx
                self.updateRGBMap(ddx, lineIndex)
        else:
            for yl in range(self.starty, y - 1, -1):
                ddx = int(rat * (yl - self.starty)) + self.startx
                lineIndex = self.lengthRamp - 1 - yl
                line = self.currentLines[lineIndex]
                col, graybitmap = self.getColor(ddx, lineIndex)
                newline = c.create_rectangle(
                    j,
                    yl * self.linesPerRampValue + j,
                    1 + ddx,  # +j,
                    (yl + 1) * self.linesPerRampValue + j,
                    outline="",
                    fill=col,
                    stipple=graybitmap,
                )
                self.currentLines[lineIndex] = newline
                c.delete(line)
                self.currentValues[lineIndex] = ddx
                self.updateRGBMap(ddx, lineIndex)
        self.starty = y
        self.startY = Y
        self.startx = x
        # this flushes the output, making sure that
        # the rectangle makes it to the screen
        # before the next event is handled
        self.update_idletasks()
        self.updateCurTk(event)
        self.cmapCurrent = False
        self.update(drawRamp=False)

    ###########################################################################
    ##   CALLBACK FUNCTIONS
    ###########################################################################
    def apply_cb(self, event=None, cfgCmap=True):
        """"""
        # print "ColorMapGUI apply_cb"
        # Need to set self.guiMini, self.guiMaxi,from, to, from fill and to fill
        # to be set to the proper values.

        # Method which reconfigures the colormap associated to the gui
        self.configureCmap()

    def fileOpenAsk(self, idir=None, ifile=None, types=None, title="Open"):
        if types == None:
            types = [("All files", "*")]
        file = tkinter.filedialog.askopenfilename(
            filetypes=types, initialdir=idir, initialfile=ifile, title=title
        )
        if file == "":
            file = None
        return file

    def fileSaveAsk(self, idir=None, ifile=None, types=None, title="Save"):
        if types == None:
            types = [("All files", "*")]
        file = tkinter.filedialog.asksaveasfilename(
            filetypes=types, initialdir=idir, initialfile=ifile, title=title
        )
        if file == "":
            file = None
        return file

    def button_cb(self, event=None):
        """call back function for the buttons allowing to toggle between
        different canvases.
        This function hides the currentCanvas and shows the canvas
        corresponding to the active radio button.
        In addition it sets
             self.currentCanvas : used to hide it next time we come in
             self.currentLines : list of Canvas Line objects (one per canvas)
             self.currentValues : list of numerical rightXVals (one per canvas)
             self.getColor =  function to be called to represent a color as a
                              Tk string
        """
        var = self.currentCanvasVar.get()

        if var == "Hue":
            self.drawHue()
        elif var == "Sat":
            self.drawSaturation()
        elif var == "Val":
            self.drawValue()
        elif var == "Opa":
            self.drawOpacity()

        newCanvas = self.canvas[var]
        self.currentCanvas.forget()
        newCanvas.pack(side="top")
        self.currentCanvas = newCanvas
        self.currentLines = self.lines[var]
        self.currentValues = self.rightXVals[var]
        self.getColor = self.getColorFunc[var]
        self.current = var

    def min_cb(self, event=None):
        minVal = self.minTk.get()
        try:
            minVal = float(minVal)
            if self.guiMaxi is not None and minVal >= self.guiMaxi:
                raise ValueError
            self.update(mini=minVal)
        except:
            self.minTk.set("")
            self.guiMini = None
            return

    def max_cb(self, event=None):
        maxVal = self.maxTk.get()
        try:
            maxVal = float(maxVal)
            if self.guiMini is not None and maxVal <= self.guiMini:
                raise ValueError
            self.update(maxi=maxVal)
        except:
            self.maxTk.set("")
            self.guiMaxi = None
            return

    def rename_cb(self, event=None):
        self.name = self.nameVar.get()
        self.update(cmapName=self.name)
        self.legend.Set(name=self.name)
        if self.legend.ownGui is not None:
            self.legend.ownGui.title(self.legend.name)
        if self.viewer is not None:
            self.viewer.Redraw()

    def quit(self):
        # print "quit"
        self.master.destroy()

    def dismiss(self):
        # print "dismiss"
        if self.master.winfo_ismapped():
            self.master.withdraw()

    def resetAll_cb(self, event=None):
        self.cmapResetAll = True
        self.update(ramp=deepCopySeq(self.history[0]), cfgCmap=False)

    #    def reset_cb(self, event=None):
    #        """reset only the currently visible property canvas"""
    #        var = self.currentCanvasVar.get()
    #        self.deleteCanvasLines(var)
    #        ramp = deepCopySeq(self.history[0])
    #
    #        self.lengthRamp = len(ramp)
    #        if self.lengthRamp > self.height :
    #            self.height = self.lengthRamp
    #        self.numOfRampValues.set( self.lengthRamp )
    #
    #        hsva = map(lambda x, conv=RGBA2HSLA_list: conv(x), ramp)
    #        ind = self.idList.index(var)
    #        #format?...list?....array??
    #        newVals = Numeric.array(hsva)[:,ind]
    #        self.guiRamp = self.buildRGBMap(ind, newVals)
    #
    #        self.cmapCompToReset = var
    #        if var == 'Hue':
    #            self.setRightXVals('Hue')
    #            self.drawHue()
    #        elif var == 'Sat':
    #            self.setRightXVals('Sat')
    #            self.drawSaturation()
    #        elif var == 'Val':
    #            self.setRightXVals('Val')
    #            self.drawValue()
    #        elif var == 'Opa':
    #            self.setRightXVals('Opa')
    #            self.drawOpacity()
    #        if self.continuousUpdate.get():
    #            self.configureCmap()
    #        #self.mouseUp(None) # to call callbacks
    #        self.currentValues = self.rightXVals[var]
    #        self.ogl_cmw.ramp = self.guiRamp[:]
    #        self.ogl_cmw.tkRedraw()

    def stepBack_cb(self):
        # update self.ramp to last ramp on history list
        if len(self.history) == 1 and self.cmapCurrent is True:
            return

        if self.cmapCurrent and self.nbStepBack == 0:
            index = self.nbStepBack + 2
        else:
            index = self.nbStepBack + 1

        self.nbStepBack = index
        newind = len(self.history) - index
        cfgCmap = True

        if newind < 0:
            # tried to go back too far
            newind = 0
            self.nbStepBack = 0

        if newind == 0:
            # only valid for continuous mode.
            # want to go back to the first entry of the history which
            # stays so we don't need to update the cmap
            cfgCmap = False
        self.update(ramp=self.history[newind], cfgCmap=cfgCmap)

    def read_cb(self):
        fileTypes = [("ColorMap", "*_map.py"), ("any file", "*.*")]
        fileBrowserTitle = "Read Color Map"
        fileName = self.fileOpenAsk(types=fileTypes, title=fileBrowserTitle)
        if not fileName:
            return

        self.read(fileName)

    def read(self, filename):

        ColorMap.read(self, filename)
        self.configureGui(ramp=self.ramp, mini=self.mini, maxi=self.maxi)

        if self.legend.viewer:
            # self.legend.RedoDisplayList()
            self.legend.viewer.Redraw()
            # self.configureCmap()

    def enter_cb(self, event=None):
        if widgetsOnBackWindowsCanGrabFocus is False:
            lActiveWindow = self.focus_get()
            if lActiveWindow is not None and (
                lActiveWindow.winfo_toplevel() != self.winfo_toplevel()
            ):
                return

        self.focus_set()

    def leave_cb(self, event=None):
        pass

    ############################################################
    ### UTILITY FUNCTIONS
    ############################################################
    def makeEvent(self, x, y):
        xval = x * self.xrange + self.xoffset
        return DummyEvent(xval, y)

    def hueColor(self, val, rampIndex):
        """TkColorString <- hueColor(val)
        val is an integer between self.xoffset and self.width.
        (default:val is an integer between 25 and 200.)
        returns color to be use to draw hue lines in hue canvas"""
        # print "hueColor", h
        if val > self.width:
            h = 1
        else:
            h = float(self.width - val) / self.xrange  # * .999 #*.6666666667
        #        if h == 0:
        #            h = 1
        self.currentHue[rampIndex] = h
        rgb = HSL2RGB(h, 1.0, 0.5)
        graybitmap = ""
        return TkColor(rgb), graybitmap

    def satColor(self, val, rampIndex):
        """TkColorString <- satColor(val)
        val is an integer between self.xoffset and self.width.
        (default:val is an integer between 25 and 200.)
        returns color to be use to draw saturation lines in saturation canvas"""
        # print "satColor", val, rampIndex
        if val < self.xoffset:
            x = 0
        else:
            x = float(val - self.xoffset) / self.xrange
        self.currentSat[rampIndex] = x
        rgb = HSL2RGB(self.currentHue[rampIndex], x, 0.5)
        rgb.append(1.0)
        graybitmap = ""
        return TkColor(rgb), graybitmap

    def valColor(self, val, rampIndex):
        """TkColorString <- valColor(val)
        val is an integer between 25 and 200
        returns color to be used to draw value and opacity lines in canvas"""
        # print "valColor", val, rampIndex
        if val < self.xoffset:
            x = 0
        else:
            x = float(val - self.xoffset) / self.xrange
        rgb = HSL2RGB(self.currentHue[rampIndex], self.currentSat[rampIndex], x)
        rgb.append(1.0)
        graybitmap = ""
        return TkColor(rgb), graybitmap

    def opaColor(self, val, rampIndex=None):
        # print "opaColor"
        if val < self.xoffset:
            x = 0
        else:
            x = float(val - self.xoffset) / self.xrange

        if x >= 1:
            graybitmap = ""
            col = "black"
        elif x > 0.75:
            graybitmap = "gray75"
            col = "black"
        elif x > 0.50:
            graybitmap = "gray50"
            col = "black"
        elif x > 0.25:
            graybitmap = "gray25"
            col = "black"
        elif x > 0:
            graybitmap = "gray12"
            col = "black"
        else:
            graybitmap = ""
            col = ""
        return col, graybitmap

    def opaColor_Unused(self, val, rampIndex=None):
        # the color of the dot changes
        # we don't use it because the limit line drawn is less visible

        x = float(val - self.xoffset) / self.xrange
        background = self.canvas["Opa"].configure()["background"]
        backgroundHSV = ToHSV(background[4], mode="HEX", flag255=0)
        bgHSV = [backgroundHSV[0], backgroundHSV[1], backgroundHSV[2] * (1 - x)]
        col = ToHEX(bgHSV, mode="HSV")
        if x >= 1:
            graybitmap = ""
        elif x > 0.75:
            graybitmap = "gray75"
        elif x > 0.50:
            graybitmap = "gray50"
        elif x > 0.25:
            graybitmap = "gray25"
        elif x > 0:
            graybitmap = "gray12"
        else:
            graybitmap = ""
        return col, graybitmap

    #    def createCMLWidget(self):
    #        self.legend_gui = Tkinter.Toplevel()
    #        self.legend_gui.title(self.legend.name)
    #        self.legend_gui.protocol('WM_DELETE_WINDOW', self.legend_gui.withdraw )
    #
    #        frame1 = Tkinter.Frame(self.legend_gui)
    #        frame1.pack(side='top')
    #
    #        #unit
    #        self.unitsEnt = Pmw.EntryField(frame1,
    #                                       label_text='Units  ',
    #                                       labelpos='w',
    #                                       command=self.updateCML_cb)
    #        self.unitsEnt.pack(side='top', fill='x')
    #
    #        #glf vector font
    #        self.glfFont = Tkinter.StringVar()
    #        self.glfFont.set('chicago1.glf')
    #        self.glfFontCB = Pmw.ComboBox(frame1, label_text='Font    ',
    #                                   labelpos='w',
    #                                   entryfield_value=self.glfFont.get(),
    #                                   scrolledlist_items=ColorMapLegend.glfVectorFontList,
    #                                   selectioncommand=self.updateCML_cb)
    #        self.glfFontCB.pack(side='top', fill='x')
    #
    #        #fontScale
    #        self.fontScale = ThumbWheel(frame1,
    #                                    labCfg={'text':'font scale            ', 'side':'left'},
    #                                    showLabel=1,
    #                                    width=90,
    #                                    height=14,
    #                                    min=0,
    #                                    max=200,
    #                                    type=int,
    #                                    value=self.legend.fontScale,
    #                                    callback=self.updateCML_cb,
    #                                    continuous=True,
    #                                    oneTurn=10,
    #                                    wheelPad=0)
    #        self.fontScale.pack(side='top')
    #
    #        #label
    #        self.labelValsEnt = Pmw.EntryField(
    #                                frame1,
    #                                label_text='Numeric labels    ',
    #                                labelpos='w',
    #                                command=self.updateCML_cb)
    #        self.labelValsEnt.component('entry').config(width=6)
    #        self.labelValsEnt.pack(side='top', fill='x')
    #
    #        #numOfLabel
    #        self.numOfLabelsCtr = ThumbWheel(frame1,
    #                                    labCfg={'text':'Automatic labels', 'side':'left'},
    #                                    showLabel=1,
    #                                    width=90,
    #                                    height=14,
    #                                    min=0,
    #                                    max=200,
    #                                    type=int,
    #                                    value=5,
    #                                    callback=self.updateCML_cb,
    #                                    continuous=True,
    #                                    oneTurn=20,
    #                                    wheelPad=0)
    #        self.numOfLabelsCtr.pack(side='top')
    #
    #        # Interpolate
    #        self.interpVar = Tkinter.IntVar()
    #        self.interpVar.set(0)
    #        self.checkBoxFrame = Tkinter.Checkbutton(
    #                                frame1,
    #                                text='Interpolate',
    #                                variable=self.interpVar,
    #                                command=self.updateCML_cb)
    #        self.checkBoxFrame.pack(side='top')
    #
    #        # frame
    #        self.frameVar = Tkinter.IntVar()
    #        self.frameVar.set(1)
    #        self.checkBoxFrame = Tkinter.Checkbutton(
    #                                frame1,
    #                                text='Frame',
    #                                variable=self.frameVar,
    #                                command=self.updateCML_cb)
    #        self.checkBoxFrame.pack(side='top')
    #
    #        # invert labels color
    #        self.invertLabelsColorVar = Tkinter.IntVar()
    #        self.invertLabelsColorVar.set(0)
    #        self.checkBoxinvertLabelsColor = Tkinter.Checkbutton(
    #                                frame1,
    #                                text='Invert labels color',
    #                                variable=self.invertLabelsColorVar,
    #                                command=self.updateCML_cb)
    #        #self.checkBoxFrame.pack(side='top')
    #        self.checkBoxinvertLabelsColor.pack(side='top')
    #
    #        # colormapguiwidget:
    #        self.launchColormapWidget = Tkinter.Button(
    #                                        frame1,
    #                                        text="Show colormap settings",
    #                                        command=self.showColormapSettings_cb )
    #        self.launchColormapWidget.pack(side='top', fill='x')

    def showColormapSettings_cb(self, event=None):
        # print "showColormapSettings_cb"
        master = self.master
        while (
            hasattr(master, "deiconify") is False and hasattr(master, "master") is True
        ):
            master = master.master
        if hasattr(master, "deiconify"):
            if master.winfo_ismapped() == 0:
                master.deiconify()
            master.lift()
            # else: master.withdraw()

    def showLegendButton_cb(self, event=None):
        # print "showLegendButton_cb"
        if not self.viewer:
            return
        if not self.legend:
            self.createCML()
        visible = self.showLegendVar.get()
        self.legend.Set(visible=visible)
        # self.legend.setWithOwnGui()

        if visible == 0:
            if self.legend.viewer.currentObject is self.legend:
                self.legend.viewer.SetCurrentObject(self.legend.viewer.rootObject)

        # do you have to do a redraw to see it?
        self.viewer.Redraw()

    def showLegend(self):
        self.showLegendVar.set(1)
        self.showLegendButton_cb()

    def hideLegend(self):
        self.showLegendVar.set(0)
        self.showLegendButton_cb()

    def editLegend_cb(self, event=None):
        # print "editLegend_cb"
        if not self.legend:
            self.createCML()
        self.legend.showOwnGui()

    def resizeCanvases(self, height=None, width=None):
        # print "resizeCanvases"
        if height is not None:
            for c in list(self.canvas.values()):
                c.configure(height=height)
            self.ogl_cmw.configure(height=height)
            self.ogl_cmw.height = height

        if width is not None:
            for c in list(self.canvas.values()):
                c.configure(width=width)
            self.ogl_cmw.configure(width=width)
            self.ogl_cmw.width = width

    def buildRGBMap(self, ind, newVals):
        """ind is 0 for Hue, 1 for Sat etc
        newVals is list of new rightXValues for that column"""
        # print "buildRGBMap"
        rgbs = []
        hsva = list(map(list, list(map(RGBA2HSLA_list, self.guiRamp))))
        for i in range(len(self.guiRamp)):
            hsva[i][ind] = newVals[i]
            rgbs.append(list(HSLA2RGBA_list(hsva[i])))
        return rgbs

    def buildRightXVals(self):
        """idList = ['Hue','Sat','Opa','Val']"""
        for id in self.idList:
            self.setRightXVals(id)

    def setRightXVals(self, idStr):
        # each canvas line is drawn at constant y value
        # between x1=0 on the left and x2 which is current
        # ramp at y (which ranges between 0. and 1.) times 175
        # NB: 175 is the effective width of the canvas
        # idList = ['Hue','Sat','Opa','Val']

        # print "setRightXVals"

        if idStr not in self.idList:
            return
        ind = self.idList.index(idStr)
        # apparently these are 200-this value and
        # for entire Hue ramp delta x = .66401
        hsvaRamp = list(map(list, list(map(RGBA2HSLA_list, self.guiRamp))))
        ramp_vals = Numeric.array(hsvaRamp)[:, ind]
        norm_n = ramp_vals
        if idStr == "Hue":
            # self.width is 200 which is 25 border + 175 map
            # 25 and 175 are the default values but can be changed
            val = self.width - (norm_n * self.xrange)
        else:
            val = norm_n * self.xrange + self.xoffset
        # self.rightXVals[idStr] = map(int, val.tolist())
        self.rightXVals[idStr] = val.tolist()

    def write_cb(self):
        fileTypes = [("ColorMap", "*_map.py"), ("any file", "*.*")]
        fileBrowserTitle = "Write Color Map"
        fileName = self.fileSaveAsk(types=fileTypes, title=fileBrowserTitle)
        if not fileName:
            return
        self.write(fileName)

    def deleteCanvasLines(self, name):
        """delete all lines in ramp canvas"""
        assert name in self.idList
        # assert name in ['Hue', 'Sat', 'Val', 'Opa' ]
        l = self.lines[name]
        c = self.canvas[name]
        for i in range(len(l)):
            c.delete(l[i])
        self.lines[name] = []
        self.rightXVals[name] = []
        self.curxTk.set("0.0")
        self.curyTk.set("0.0")
        if self.current == name:
            self.currentValues = self.rightXVals[name]
            self.currentLines = self.lines[name]

    def drawHue(self):
        j = self.canvasStart
        # print "drawHue"
        # this is for initializing and resets
        l = self.lines["Hue"]
        c = self.canvas["Hue"]
        v = self.rightXVals["Hue"]

        for i in range(len(l)):
            c.delete(l[i])
        self.lines["Hue"] = []
        l = self.lines["Hue"]

        for i in range(self.lengthRamp):
            # nb val is the LENGTH of the line to draw
            val = v[i]
            col, graybitmap = self.hueColor(val, i)
            l.append(
                c.create_rectangle(
                    j,
                    (self.lengthRamp - 1 - i) * self.linesPerRampValue + j,
                    1 + val,
                    ((self.lengthRamp - 1 - i) + 1) * self.linesPerRampValue + j,
                    fill=col,
                    outline="",
                )
            )

        if self.current == "Hue":
            self.currentLines = l

    def drawSaturation(self):
        # print "drawSaturation"
        c = self.canvas["Sat"]
        l = self.lines["Sat"]
        v = self.rightXVals["Sat"]
        j = self.canvasStart

        for i in range(len(l)):
            c.delete(l[i])
        self.lines["Sat"] = []
        l = self.lines["Sat"]

        for i in range(self.lengthRamp):
            val = v[i]
            col, graybitmap = self.satColor(val, i)
            l.append(
                c.create_rectangle(
                    j,
                    (self.lengthRamp - 1 - i) * self.linesPerRampValue + j,
                    1 + val,
                    ((self.lengthRamp - 1 - i) + 1) * self.linesPerRampValue + j,
                    fill=col,
                    outline="",
                )
            )
        if self.current == "Sat":
            self.currentLines = l

    def drawValue(self):
        c = self.canvas["Val"]
        l = self.lines["Val"]
        v = self.rightXVals["Val"]
        j = self.canvasStart

        for i in range(len(l)):
            c.delete(l[i])
        self.lines["Val"] = []
        l = self.lines["Val"]

        for i in range(self.lengthRamp):
            val = v[i]
            col, graybitmap = self.valColor(val, i)
            # print "val i col", val, i, col
            l.append(
                c.create_rectangle(
                    j,
                    (self.lengthRamp - 1 - i) * self.linesPerRampValue + j,
                    1 + val,
                    ((self.lengthRamp - 1 - i) + 1) * self.linesPerRampValue + j,
                    fill=col,
                    outline="",
                )
            )
        if self.current == "Val":
            self.currentLines = l

    def drawOpacity(self):
        c = self.canvas["Opa"]
        l = self.lines["Opa"]
        v = self.rightXVals["Opa"]
        j = self.canvasStart

        for i in range(len(l)):
            c.delete(l[i])
        self.lines["Opa"] = []
        l = self.lines["Opa"]

        for i in range(self.lengthRamp):
            val = v[i]
            col, graybitmap = self.opaColor(val)
            l.append(
                c.create_rectangle(
                    j,
                    (self.lengthRamp - 1 - i) * self.linesPerRampValue + j,
                    1 + val,
                    ((self.lengthRamp - 1 - i) + 1) * self.linesPerRampValue + j,
                    outline="",
                    fill=col,
                    stipple=graybitmap,
                )
            )
        if self.current == "Opa":
            self.currentLines = l

    def addCallback(self, function):
        assert hasattr(function, "__call__")
        self.callbacks.append(function)

    def callCallbacks(self):
        for f in self.callbacks:
            f(self)

    def valueAtY(self, y):
        # compute the value for q given line in canvas
        y = y - self.canvasStart
        y = max(y, 0)
        y = min(y, self.height - 1)
        if self.guiMini is not None and self.guiMaxi is not None:
            range = self.guiMaxi - self.guiMini
            return (float(self.height - y) / (self.height - 1)) * range + self.guiMini
        else:
            return int((self.height - y) / self.linesPerRampValue)

    def indexAtY(self, y):
        # compute the value for q given line in canvas
        j = self.canvasStart
        Y = min(j + self.height - 1, y)
        if Y < j:
            Y = j
        y = int((Y - j) / self.linesPerRampValue)
        return y

    def updateCurTk(self, event):
        x = event.x  # - self.canvasStart
        x = max(x, self.xoffset)
        x = min(x, self.width)
        val = (x - self.xoffset) / self.xrange
        self.curxTk.set("%4.2f" % val)
        lVal = self.valueAtY(event.y)
        if lVal is not None:
            self.curyTk.set("%4.2f" % lVal)
        else:
            self.curyTk.set("")
        if self.labels is not None:
            self.labelsComboBox.selectitem(self.indexAtY(event.y))

    def updateOGLwidget(self):
        self.ogl_cmw.tkRedraw()

    def updateRGBMap(self, x, y):

        cur_val = list(RGBA2HSLA_list(self.guiRamp[y]))
        cur_val[0] = self.currentHue[y]
        cur_val[1] = self.currentSat[y]

        if self.current == "Hue":
            h = ((self.width - x) / self.xrange) * 0.999  # *.6666666667
            cur_val[0] = round(h, 3)
        else:
            # use keyList = ['Sat', 'Val', 'Opa']
            keyList = self.idList[1:]
            ind = keyList.index(self.current) + 1
            h = (x - self.xoffset) / self.xrange
            cur_val[ind] = round(h, 3)
        self.guiRamp[y] = list(HSLA2RGBA_list(cur_val))


class OGLColorMapWidget(OGLWidget):
    """This object provides a OpenGL window that displays an RGBA color map"""

    def __init__(
        self,
        master,
        cmap,
        title="OGLColorMapWidget",
        width=None,
        height=None,
        cnf=None,
        **kw
    ):

        if width is None:
            kw["width"] = 19
        else:
            kw["width"] = width
        if height is None:
            kw["height"] = 180
        else:
            kw["height"] = height

        self.callback = None

        assert isinstance(cmap, ColorMap)
        self.ramp = deepCopySeq(cmap.ramp)
        self.step = 1  # set to larger values to accelerate redraw

        tf = self.topFrame = tkinter.Frame(master, borderwidth=1)
        self.frame = tkinter.Frame(tf, borderwidth=3, relief="sunken")

        if cnf is None:
            cnf = {}
        OGLWidget.__init__(*(self, self.frame, title, cnf, 0), **kw)

        self.frame.pack(expand=1, fill="both")
        self.topFrame.pack(expand=1, fill="both")
        self.pack(side="left", expand=1, fill="both")
        # self.initTexture()

    def tkRedraw(self, *dummy):
        """guillaume: probably useless, the code is almost identical
        in the overriden function OGLWidget.tkRedraw"""
        self.update_idletasks()
        self.tk.call(self._w, "makecurrent")
        self.initProjection()
        GL.glPushMatrix()
        self.redraw(*dummy)  # guillaume: self.redraw() in OGLWidget.tkRedraw
        GL.glFlush()
        GL.glPopMatrix()
        self.tk.call(self._w, "swapbuffers")

    def redraw(self, line=None):
        # print "redraw"
        drawLegendOnly(
            fullWidth=self.width,
            fullHeight=self.height,
            ramp=self.ramp,
            verticalLegend=True,
            roomLeftToLegend=0,
            roomBelowLegend=0,
            legendShortSide=self.width,
            legendLongSide=self.height,
            interpolate=False,
            selected=False,
        )
        return


if __name__ == "__main__":
    # import pdb

    # test = ColorMapGUI()
    # def cb(ramp, min, max):
    # print len(ramp), min, max
    # test.addCallback(cb)

    ##cm = ColorMap('cmap', filename='/home/rhuey/python/dev/rgb.map')
    # cmg = ColorMapGUI(cm, allowRename=1)

    l = {}
    g = {}
    exec(
        compile(open("Tests/rgb256_map.py").read(), "Tests/rgb256_map.py", "exec"), g, l
    )
    cm = None
    # for name, object in l.items():
    #    if isinstance(object, ColorMap):
    #        cm = object
    #        break
    cm = l["cm"]

    from DejaVu import Viewer

    vi = Viewer()
    cmg = ColorMapGUI(cm, allowRename=1, viewer=vi)

# test.mainloop()

## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by

#############################################################################
#
# Author: <NAME>
#
# Copyright: <NAME> TSRI 2000
#
# Revision: <NAME>
#
#############################################################################
#
# $Header$
#
# $Id$
#

import types, numpy.oldnumeric as Numeric, os, sys
import tkinter, Pmw
import tkinter.filedialog

# from string import strip, split, find

from opengltk.OpenGL import GL
from opengltk.extent import _gllib as gllib
from mglutil.util.misc import deepCopySeq
from mglutil.gui.BasicWidgets.Tk.thumbwheel import ThumbWheel
from mglutil.util.colorUtil import (
    HSL2RGB,
    RGB2HSL,
    RGBA2HSLA_list,
    HSLA2RGBA_list,
    ToHSV,
    ToHEX,
)
from mglutil.gui import widgetsOnBackWindowsCanGrabFocus

from DejaVu import viewerConst
from DejaVu.colorMap import ColorMap
from DejaVu.MaterialEditor import OGLWidget
from DejaVu.colorMapLegend import ColorMapLegend
from DejaVu.Geom import Geom
from DejaVu.colorTool import (
    RGBARamp,
    RedWhiteBlueRamp,
    RedWhiteRamp,
    WhiteBlueRamp,
    TkColor,
)
from DejaVu.Legend import drawLegendOnly


class ComboBoxRename(Pmw.ComboBox):
    def setExternalList(self, externalList, reverse=False, numOfBlockedLabels=0):
        self.externalList = externalList
        self.reverse = reverse
        self.numOfBlockedLabels = numOfBlockedLabels

    def _addHistory(self):
        # print "_addHistory"
        lCurSelection = self.curselection()
        if len(lCurSelection) > 0:
            lCurSelection0 = int(lCurSelection[0])
            if self.reverse is True:
                lBoolTest = (
                    len(self.externalList) - 1 - lCurSelection0
                ) >= self.numOfBlockedLabels
            else:
                lBoolTest = lCurSelection0 >= self.numOfBlockedLabels
            if lBoolTest:
                input = self._entryWidget.get()
                if (input != "") and (input not in self._list.get(0, "end")):
                    self.delete(lCurSelection0)
                    self.insert(lCurSelection0, input)
                    if self.reverse is True:
                        self.externalList[
                            len(self.externalList) - 1 - lCurSelection0
                        ] = input
                    else:
                        self.externalList[lCurSelection0] = input
            self.selectitem(lCurSelection0)
        else:
            self.selectitem(0)


class DummyEvent:
    """dummy Tkinter event """

    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y


COLORMAPGUI_MAXIMAL_HEIGHT = 1024


class ColorMapGUI(tkinter.Frame, ColorMap):
    """The ColorMapGUI is an object providing an interface to expose
    and to modify a ColorMap object.

    The ColorMapGUI has a local copy of the colormap.ramp, colormap.mini and
    colormap.maxi which will be modified through the GUI.
    The associated colormap object will only be updated when by the apply_cb
    which is called whenever a mouseUp event or update is called if the gui
    is in continuous mode or when the Aplly button is pressed when the gui is
    not in a continuous mode.

    The GUI allows the user to edit each of 4 different color
    properties: 'Hue','Sat' or saturation, 'Val' or value
    and 'Opa' or opacity for each entry in the ramp of the
    ColorMap. This is implemented via 4 Canvases, one for
    each color property. (Drawing on a canvas is done by
    pressing the left mouse button over the canvas and
    holding it down while moving the mouse.)
    Drawing at a point 'x','y', on one of the canvases changes
    the value of the corresponding color property in this way:
    'y' specifies the entry in the ColorMap.ramp to be changed.
    'x' is first normalized to give a value between 0 and 1.0.
    (by dividing it by the effective canvas width).
    A new rgba value is built from the hsva list comprised of
    3 previous values and this new normalized 'x' in the
    appropriate position. (that is, if the user is drawing on
    the 'Hue' canvas, the normalized 'x' value replaces the 'h',
    or zeroth entry,etc).

    If the GUI has a viewer, an OpenGLColorMapWidget is constructed
    which displays the GUI's current rgbMap. Also, the user can choose
    to add a ColorMapLegend to the viewer which displays the current
    ColorMap.ramp and which can be labeled."""

    staticRamp = RGBARamp(size=128, upperValue=0.85).tolist()

    def __init__(
        self,
        cmap=None,
        master=None,
        continuous=0,
        allowRename=True,
        modifyMinMax=False,
        viewer=None,
        xoffset=25,
        width=200,
        height=256,
        geoms=None,
        name=None,
        ramp=None,
        labels=None,
        mini=None,
        maxi=None,
        filename=None,
        show=True,
        numOfBlockedLabels=0,
        **kw
    ):

        # this is the active colormap
        if cmap is None:
            ColorMap.__init__(
                self,
                name=name,
                ramp=ramp,
                labels=labels,
                filename=filename,
                mini=mini,
                maxi=maxi,
            )
        else:
            ColorMap.__init__(
                self,
                name=cmap.name,
                ramp=cmap.ramp,
                labels=cmap.labels,
                mini=cmap.mini,
                maxi=cmap.maxi,
            )

        self.history = []
        self.legend = None
        if geoms is None:
            geoms = {}
        self.geoms = geoms
        self.viewer = None
        self.currentOnStack = False
        self.numOfBlockedLabels = numOfBlockedLabels

        # initialize a bunch of flags.
        self.cmapCurrent = True
        self.cmapCompToReset = None
        self.cmapResetAll = False
        self.nbStepBack = 0

        # Initialize the local guiRamp, guiMini and guiMaxi values
        # which will be modified
        self.guiRamp = []
        self.guiMini = None
        self.guiMaxi = None
        if self.labels is not None:
            self.guiLabels = deepCopySeq(self.labels)
        self.colorbin = []
        self.labelbin = []
        self.lengthRamp = len(self.ramp)

        if height < self.lengthRamp:
            height = self.lengthRamp

        self.height = height
        self.linesPerRampValue = self.height / float(self.lengthRamp)
        self.currentHue = []
        self.currentSat = []

        # Create parts of the GUI
        if master is None:
            if viewer:
                theMaster = tkinter.Toplevel(viewer.master)
            else:
                theMaster = tkinter.Toplevel()
        else:
            theMaster = master

        if hasattr(theMaster, "protocol"):
            theMaster.protocol("WM_DELETE_WINDOW", self.dismiss)

        # we hide it if it was asked
        if show is False:
            master2 = theMaster
            while (
                hasattr(master2, "withdraw") is False
                and hasattr(master2, "master") is True
            ):
                master2 = master2.master
            master2.withdraw()

        tkinter.Frame.__init__(self, theMaster)
        tkinter.Pack.config(self, expand=1, fill="both")
        if hasattr(theMaster, "title"):
            theMaster.title(self.name)
        # Canvas width (default=200)
        self.width = width

        self.canvasStart = 4

        # left border width (default=25)
        self.xoffset = xoffset
        # Available drawing width default=width-xoffset
        self.xrange = float(width - xoffset)

        # DejaVu viewer to which colorMapLegend is added
        self.viewer = None

        self.continuousUpdate = tkinter.IntVar()
        self.continuousUpdate.set(continuous)

        # if allowRename is False, name entry is disabled.
        self.allowRename = allowRename
        self.modifyMinMax = modifyMinMax

        self.idList = ["Hue", "Sat", "Val", "Opa"]
        self.getColorFunc = {
            "Hue": self.hueColor,
            "Sat": self.satColor,
            "Val": self.valColor,
            "Opa": self.opaColor,
        }

        # initialize dictionaries
        # NB all the lines end at xpoints corresponding to the
        # the colorproperty value at that point... (except
        #'Hue' is backwards, width-property+xoffset instead of
        # property+xoffset)

        self.rightXVals = {}
        self.lines = {}
        for idStr in self.idList:
            self.rightXVals[idStr] = []
            self.lines[idStr] = []

        self.current = "Hue"  # name of the currently visible prop. canvas
        self.callbacks = []  # list of functions to be called when apply
        # button is pressed or ramp is modified and
        # mode is continuous update

        # Calls the createWidgets method to create the 4 canvases
        # and the buttons.
        self.createWidgets(theMaster)
        self.configureGui(
            ramp=self.ramp,
            geoms=self.geoms,
            legend=self.legend,
            labels=self.labels,
            mini=self.mini,
            maxi=self.maxi,
            **kw
        )

        # Call the update to initialize the gui with the given cmap values,
        # without configuring the cmap
        self.update(
            mini=self.mini, maxi=self.maxi, ramp=deepCopySeq(self.ramp), cfgCmap=False
        )
        self.cmapCurrent = True

        # set current colorFunc, lines and values to 'Hue'
        self.getColor = self.getColorFunc["Hue"]
        self.currentLines = self.lines["Hue"]
        self.currentValues = self.rightXVals["Hue"]

        tkinter.Widget.bind(self, "<Enter>", self.enter_cb)
        tkinter.Widget.bind(self, "<Leave>", self.leave_cb)

        # set-up canvas mouse bindings:
        for idStr in ["Hue", "Sat", "Val", "Opa"]:
            tkinter.Widget.bind(self.canvas[idStr], "<ButtonPress-1>", self.mouseDown)
            tkinter.Widget.bind(
                self.canvas[idStr], "<Button1-Motion>", self.mouseMotion
            )
            tkinter.Widget.bind(self.canvas[idStr], "<ButtonRelease-1>", self.mouseUp)

            tkinter.Widget.bind(self.canvas[idStr], "<Motion>", self.updateCurTk)

            tkinter.Widget.bind(
                self.canvas[idStr], "<ButtonPress-3>", self.mouseDownRight
            )
            tkinter.Widget.bind(
                self.canvas[idStr], "<Button3-Motion>", self.mouseMotionRight
            )
            tkinter.Widget.bind(
                self.canvas[idStr], "<ButtonRelease-3>", self.mouseUpRight
            )

            self.canvas[idStr].configure(cursor="cross")

        self.straightLine = None

        # create the cml
        if self.legend is None:
            self.createCML()

        self.SetViewer(viewer)

        #        # fields created by the CMLwidget
        #        self.legend.createOwnGui()
        #        self.legend.hideOwnGui()

        if master is not None:
            master2 = theMaster
            if hasattr(master2, "master") is True and isinstance(
                master2.master, tkinter.Widget
            ):
                master2 = master2.master
            if hasattr(master2, "master") is True and isinstance(
                master2.master, tkinter.Widget
            ):
                master2 = master2.master
            # Tkinter.Widget.bind(master2, '<Configure>', self.configure_cb)
            self.inVision = True
        else:
            tkinter.Widget.bind(self.fullWidgetFrame, "<Configure>", self.configure_cb)
            self.inVision = False

    def configure_cb(self, event=None):
        # print "configure_cb", event, dir (event)
        # print "configure_cb event.height", event.height

        #        self.width = event.width
        #        self.xrange = float(self.width - self.xoffset)

        if self.inVision is True:
            height = (
                event.height
                - 2 * self.canvasStart
                - self.menuFrame1.winfo_reqheight()
                - self.buttonFrame.winfo_reqheight()
                - 73
            )
        elif os.name == "nt":  # sys.platform == 'win32':
            height = (
                event.height
                - 2 * self.canvasStart
                - self.menuFrame1.winfo_reqheight()
                - self.buttonFrame.winfo_reqheight()
                - self.frame2.winfo_reqheight()
                - 2
            )
        else:
            height = (
                event.height
                - 2 * self.canvasStart
                - self.menuFrame1.winfo_reqheight()
                - self.buttonFrame.winfo_reqheight()
                - self.frame2.winfo_reqheight()
            )

        # print "configure_cb height", height
        if height >= self.lengthRamp and height > 0:
            self.height = height
            # print "self.height 1", self.height
            self.linesPerRampValue = self.height / float(self.lengthRamp)
            self.resizeCanvases(self.height)
            self.drawRampCanvases(drawRamp=True)

    def changeRampLength_cb(self, numOfRampValue):
        # print "changeRampLength_cb", numOfRampValue, len(self.guiRamp), len(self.ramp)
        # import traceback;traceback.print_stack()

        lenguiramp = len(self.guiRamp)
        if numOfRampValue < self.numOfBlockedLabels:
            self.numOfRampValues.set(lenguiramp)
            return
        elif numOfRampValue == lenguiramp:
            return
        elif numOfRampValue < lenguiramp:
            for i in range(numOfRampValue, lenguiramp):
                self.colorbin.append(self.guiRamp.pop())
        else:  # numOfRampValue > lenguiramp:
            lNumOfColorsToAdd = numOfRampValue - lenguiramp
            lNumOfColorsToCreate = lNumOfColorsToAdd - len(self.colorbin)
            if lNumOfColorsToCreate > 0:
                for i in range(len(self.colorbin)):
                    self.guiRamp.append(self.colorbin.pop())
                for i in range(lNumOfColorsToCreate):
                    lIndex = len(self.guiRamp) % len(self.staticRamp)
                    self.guiRamp.append(self.staticRamp[lIndex])
            else:
                for i in range(lNumOfColorsToAdd):
                    self.guiRamp.append(self.colorbin.pop())

        self.configureGui(
            ramp=self.guiRamp,
            mini=self.mini,
            maxi=self.maxi,
            updateGui=True,
            theGivenRampIsTheGuiRamp=True,
            # guiRamp=self.guiRamp
        )
        self.cmapCurrent = False

    def adjustGuiLabels(self, newNumOfGuiLabels):
        # print "adjustGuiLabels", newNumOfGuiLabels

        lenguiLabels = len(self.guiLabels)
        if newNumOfGuiLabels == lenguiLabels:
            return
        elif newNumOfGuiLabels < lenguiLabels:
            for i in range(newNumOfGuiLabels, lenguiLabels):
                self.labelbin.append(self.guiLabels.pop())
        else:
            lNumOfLabelsToAdd = newNumOfGuiLabels - lenguiLabels
            lNumOfLabelsToCreate = lNumOfLabelsToAdd - len(self.labelbin)
            if lNumOfLabelsToCreate > 0:
                for i in range(len(self.labelbin)):
                    self.guiLabels.append(self.labelbin.pop())
                for i in range(lNumOfLabelsToCreate):
                    self.guiLabels.append(str(len(self.guiLabels)))
            else:
                for i in range(lNumOfLabelsToAdd):
                    self.guiLabels.append(self.labelbin.pop())
        self.configureGui(labels=self.guiLabels)

    def createCML(self):
        """create the ColorMap Legend"""
        if self.legend:
            return
        # width defaults to len(ramp); height defaults to 1
        # mini, maxi and interp set from self
        cmlOptions = {"width": 10, "height": 1, "name": self.name, "ramp": self.ramp}

        if self.mini is not None:
            cmlOptions["mini"] = self.mini

        if self.maxi is not None:
            cmlOptions["maxi"] = self.maxi

        self.legend = ColorMapLegend(*(self,), **cmlOptions)

    #    def resetComp(self, comp):
    #        """resets on component to first entry in history list"""
    #        compNum = ['Hue','Sat','Val','Opa'].index(comp)
    #        # Get the first entry in the history list
    #        hist = self.history[0]
    #        # Remove all the entries in the history list
    #        self.history = self.history[:1]
    #
    #        # Transform the history RGBramp into a HSL ramp
    #        histHSL = map(lambda x: list(RGBA2HSLA_list(x)), hist)
    #        # Transform the current ramp in a HSL ramp
    #        hsl = map(lambda x: list(x), self.asHSL())
    #        for i in range(len(hsl)):
    #            hsl[i][compNum] = histHSL[i][compNum]
    #        ramp = map(lambda x: list(HSLA2RGBA_list(x)), hsl)
    #        self.configure(ramp=ramp, updateGui=False)

    def reset(self):
        """return to first entry in history list"""
        ramp = self.history[0]
        self.history = []
        self.configure(ramp=deepCopySeq(ramp), updateGui=False)

    def pushRamp(self):
        """
        The pushRamp method appends the current ramp stored in cmap.ramp at the
        end of the history list.
        The attribute self.currentOnStack is set to True.
        """
        # append the current ramp to the history if the ramp is not None and
        # if the ramp has not been pushed onto the history stack yet.
        if self.ramp is None or self.currentOnStack:
            return
        self.history.append(deepCopySeq(self.ramp))
        self.currentOnStack = True

    def popRamp(self, index=-1):
        """
        optional arguments
        index -- default -1, specifies the index of the ramp to pop.
                 It is a negative index
                 as we are popping ramps from the end of the history list.

        The popRamp method will save the ramp stored at the given index
        in cmap.ramp then remove all the entry from the ramp (included)
        till the end of the history list.
        After a popRamp the attribute self.currentOnStack is False.
        """
        # Need at least one entry in the history
        if not len(self.history):
            return

        # Always keep the first entry of the history
        if len(self.history) == 1:
            if not self.currentOnStack:
                self.ramp = self.history[0]
                self.currentOnStack = True
            return
        # PopRamp removes entry from the end of the history list
        # which is why the index has to be negative.
        assert index < 0

        # 1- set the actual ramp to be the entry of history
        # corresponding to the given index
        # 2- history = history[:index]
        # the popped history is not on the stack any longer except
        # when it is the first entry

        # Get the index from the beginning of the history list
        newind = len(self.history) + index
        pushRamp = False
        if newind <= 0:
            newind = 0
            # Always keep the first entry in the history list
            pushRamp = True

        elif newind >= len(self.history):
            newind = -1
            pushRamp = False

        ramp = self.history[newind]
        self.history = self.history[:newind]
        # We do not want to push the ramp we are popping onto the history stack
        # the current ramp will not be on the history stack any longer.
        self.configure(ramp=deepCopySeq(ramp), updateGui=False, pushRamp=pushRamp)

    def SetViewer(self, viewer):
        """to give a viewer reference to the ColorMapGUI even
        after it's creation"""
        if viewer:
            if self.viewer is not None:

                self.viewer.RemoveObject(self.legend)

            self.viewer = viewer
            self.createCML()

            self.legend.name = self.viewer.ensureUniqueName(self.legend.name)
            self.update(cmapName=self.legend.name)

            self.legend.replace = False
            # self.legend.protected = True
            self.viewer.AddObject(self.legend, redo=0)

            self.showLegendVar = tkinter.IntVar()
            self.showLegendButton = tkinter.Checkbutton(
                self.buttonFrame,
                text="show legend",
                variable=self.showLegendVar,
                command=self.showLegendButton_cb,
            )
            self.showLegendButton.grid(row=5, column=0, columnspan=2, sticky="w")

    def createWidgets(self, master):
        """create Tkinter widgets: 4 canvas and buttons in 2 frames"""
        # print "createWidgets"
        self.fullWidgetFrame = tkinter.Frame(master)
        self.fullWidgetFrame.pack(side="top", expand=1, fill="both")

        # create menu frame
        self.menuFrame1 = tkinter.Frame(
            self.fullWidgetFrame, relief="raised", borderwidth=3
        )
        self.menuFrame1.pack(side="top", expand=1, fill="x")

        filebutton = tkinter.Menubutton(self.menuFrame1, text="File")
        filebutton.pack(side="left")
        filemenu = tkinter.Menu(filebutton, {})
        filemenu.add_command(label="Read", command=self.read_cb)
        filemenu.add_command(label="Write", command=self.write_cb)
        filebutton["menu"] = filemenu

        editbutton = tkinter.Menubutton(self.menuFrame1, text="Edit")
        editbutton.pack(side="left", anchor="w")
        editmenu = tkinter.Menu(editbutton, {})
        editmenu.add_command(
            label="Reset to first in history", command=self.resetAll_cb
        )
        editmenu.add_command(
            label="Step back in history loop", command=self.stepBack_cb
        )
        ##         editmenu.add_checkbutton(label='Preview', variable=self.preview)
        editmenu.add_checkbutton(label="Continuous", variable=self.continuousUpdate)

        editmenu.add_command(label="Edit Legend", command=self.editLegend_cb)

        editbutton["menu"] = editmenu

        self.numOfRampValues = ThumbWheel(
            self.menuFrame1,
            labCfg={"text": "Num of colors:", "side": "left"},
            showLabel=1,
            width=80,
            height=16,
            min=1,
            max=COLORMAPGUI_MAXIMAL_HEIGHT,
            type=int,
            value=self.lengthRamp,
            callback=self.changeRampLength_cb,
            continuous=True,
            oneTurn=60,
            wheelPad=2,
        )
        self.numOfRampValues.pack(side="right", anchor="e")

        # create canvas frames
        self.canvasesFrame = tkinter.Frame(self.fullWidgetFrame)

        # create a frame for rproperties canvases
        self.propCanvasFrame = tkinter.Frame(self.canvasesFrame)

        # create 4 canvases
        self.canvas = {}
        for idStr in self.idList:
            self.canvas[idStr] = tkinter.Canvas(
                self.propCanvasFrame,
                relief="sunken",
                borderwidth=3,
                width=self.width,
                height=self.height,
            )
        # pack Hue to start with
        self.canvas["Hue"].pack(side="left", expand=1, fill="both")
        self.propCanvasFrame.pack(side="left", expand=1, fill="both")

        self.ogl_cmw = OGLColorMapWidget(
            self.canvasesFrame,
            self,
            width=19,
            height=self.height,
        )

        self.canvasesFrame.pack(side="top", expand=1, fill="both")

        # create a frame for buttons
        self.buttonFrame = tkinter.Frame(
            self.fullWidgetFrame, relief="ridge", borderwidth=3
        )

        # create radio buttons to switch between canvas
        self.currentCanvasVar = tkinter.StringVar()
        self.buttonHue = tkinter.Radiobutton(
            self.buttonFrame,
            text="Hue",
            value="Hue",
            width=8,
            indicatoron=0,
            variable=self.currentCanvasVar,
            command=self.button_cb,
        )
        self.buttonHue.grid(row=0, column=0, sticky="we")  # pack(side='left')

        self.buttonSat = tkinter.Radiobutton(
            self.buttonFrame,
            text="Sat.",
            value="Sat",
            width=8,
            indicatoron=0,
            variable=self.currentCanvasVar,
            command=self.button_cb,
        )
        self.buttonSat.grid(row=0, column=1, sticky="we")  # pack(side='left')

        self.buttonVal = tkinter.Radiobutton(
            self.buttonFrame,
            text="Lum.",
            value="Val",
            width=8,
            indicatoron=0,
            variable=self.currentCanvasVar,
            command=self.button_cb,
        )
        self.buttonVal.grid(row=0, column=2, sticky="we")  # pack(side='left')

        self.buttonOpa = tkinter.Radiobutton(
            self.buttonFrame,
            text="Opa.",
            value="Opa",
            width=8,
            indicatoron=0,
            variable=self.currentCanvasVar,
            command=self.button_cb,
        )
        self.buttonOpa.grid(row=0, column=3, sticky="we")  # pack(side='left')

        self.currentCanvas = self.canvas["Hue"]
        self.currentCanvasVar.set("Hue")

        # name
        self.nameVar = tkinter.StringVar()
        if self.name is not None:
            self.nameVar.set(self.name)
        a = tkinter.Label(self.buttonFrame, text="name")
        a.grid(row=2, column=0, sticky="e")
        if self.allowRename is True:
            self.nameEntry = tkinter.Entry(
                self.buttonFrame, textvariable=self.nameVar, width=18
            )
            self.nameEntry.bind("<Return>", self.rename_cb)
            self.nameEntry.bind("<Leave>", self.rename_cb)
        else:
            self.nameEntry = tkinter.Label(
                self.buttonFrame,
                textvariable=self.nameVar,
                width=18,
                relief="groove",
                padx=2,
                pady=1,
            )
        self.nameEntry.grid(row=2, column=1, columnspan=3, sticky="w")

        # min max
        self.maxTk = tkinter.StringVar()
        if self.guiMaxi is not None:
            self.maxTk.set(("%8.2f" % self.guiMaxi))
        a = tkinter.Label(self.buttonFrame, text="max")
        a.grid(row=3, column=2, sticky="e")
        if self.modifyMinMax:
            self.maxEntry = tkinter.Entry(
                self.buttonFrame, textvariable=self.maxTk, width=8
            )
            self.maxEntry.bind("<Return>", self.max_cb)
            self.maxEntry.bind("<Leave>", self.max_cb)
        else:
            self.maxEntry = tkinter.Label(
                self.buttonFrame,
                textvariable=self.maxTk,
                width=8,
                relief="groove",
                justify="left",
                padx=2,
                pady=1,
            )
        self.maxEntry.grid(row=3, column=3, sticky="w")

        self.curyTk = tkinter.StringVar()
        a = tkinter.Label(self.buttonFrame, text="y ")
        a.grid(row=4, column=2, sticky="e")
        self.curYLabel = tkinter.Label(
            self.buttonFrame,
            textvariable=self.curyTk,
            width=8,
            relief="groove",
            justify="left",
            padx=2,
            pady=1,
        )
        self.curYLabel.grid(row=4, column=3, sticky="w")

        self.minTk = tkinter.StringVar()
        if self.guiMini is not None:
            self.minTk.set(("%8.2f" % self.guiMini))
        a = tkinter.Label(self.buttonFrame, text="min")
        a.grid(row=5, column=2, sticky="e")
        if self.modifyMinMax:
            self.minEntry = tkinter.Entry(
                self.buttonFrame, textvariable=self.minTk, width=8
            )
            self.minEntry.bind("<Return>", self.min_cb)
            self.minEntry.bind("<Leave>", self.min_cb)
        else:
            self.minEntry = tkinter.Label(
                self.buttonFrame,
                textvariable=self.minTk,
                width=8,
                relief="groove",
                justify="right",
                padx=2,
                pady=1,
            )
        self.minEntry.grid(row=5, column=3, sticky="w")

        self.curxTk = tkinter.StringVar()
        a = tkinter.Label(self.buttonFrame, text="x")
        a.grid(row=4, column=1, sticky="w")
        self.curXLabel = tkinter.Label(
            self.buttonFrame,
            textvariable=self.curxTk,
            width=8,
            relief="groove",
            justify="left",
            padx=2,
            pady=1,
        )
        self.curXLabel.grid(row=4, column=0, sticky="w")

        if self.labels is not None:
            # self.labelsInComboBox = Tkinter.StringVar()
            self.labelsComboBox = ComboBoxRename(
                self.buttonFrame, label_text="label", labelpos="w", history=1
            )
            self.labelsComboBox.setExternalList(
                self.guiLabels, reverse=True, numOfBlockedLabels=self.numOfBlockedLabels
            )
            self.labelsComboBox.grid(row=6, column=0, columnspan=4, sticky="w")

        # Apply and Dismiss go here
        self.frame2 = tkinter.Frame(self.fullWidgetFrame, relief="raise", borderwidth=3)
        f2 = self.frame2
        self.apply = tkinter.Button(f2, text="Apply", command=self.apply_cb)
        self.apply.pack(side="left", expand=1, fill="x")
        self.dismiss = tkinter.Button(f2, text="Dismiss", command=self.dismiss)
        self.dismiss.pack(side="left", expand=1, fill="x")

        f2.pack(side="bottom", expand=1, fill="x")
        self.frame2.pack(side="bottom", expand=1, fill=tkinter.X)
        self.buttonFrame.pack(side="bottom", expand=1, fill="x")

    def update(
        self,
        ramp=None,
        mini=None,
        maxi=None,
        cmapName=None,
        drawRamp=True,
        cfgCmap=True,
        theGivenRampIsTheGuiRamp=False,
        # guiRamp=None
    ):

        # Update the name of cmg if relevant
        if hasattr(self.master, "title"):
            self.master.title(cmapName)

        # Update the maxi and mini values of cmg
        if maxi is not None and mini is not None:
            if mini <= maxi:
                self.guiMaxi = maxi
                self.guiMini = mini
                self.minTk.set(("%8.2f" % self.guiMini))
                self.maxTk.set(("%8.2f" % self.guiMaxi))
            else:
                self.guiMaxi = None
                self.guiMini = None
                self.minTk.set("")
                self.maxTk.set("")
        elif maxi is not None and mini is None:
            if self.guiMini <= maxi:
                self.guiMaxi = maxi
                self.maxTk.set(("%8.2f" % self.guiMaxi))
            else:
                self.guiMaxi = None
                self.maxTk.set("")
        elif mini is not None and maxi is None:
            if mini <= self.guiMaxi:
                self.guiMini = mini
                self.minTk.set(("%8.2f" % self.guiMini))
            else:
                self.guiMini = None
                self.minTk.set("")

        # Update the cmg ramp with the one given
        if not ramp is None:
            if theGivenRampIsTheGuiRamp is False:
                self.cmapCurrent = False
                ramp = deepCopySeq(self.checkRamp(ramp))
                self.lengthRamp = len(ramp)
                if self.lengthRamp > self.height:
                    self.height = self.lengthRamp
                    # print "self.height 2", self.height
                self.numOfRampValues.set(self.lengthRamp)
                self.linesPerRampValue = self.height / float(self.lengthRamp)
                self.resizeCanvases(self.height)
                self.guiRamp = ramp
                if self.labels is not None:
                    self.adjustGuiLabels(self.lengthRamp)
                self.drawRampCanvases(drawRamp=drawRamp)
            else:
                # print "guiRamp"
                self.lengthRamp = len(ramp)
                if self.lengthRamp > self.height:
                    self.height = self.lengthRamp
                    # print "self.height 3", self.height
                # self.numOfRampValues.set(self.lengthRamp)
                self.linesPerRampValue = self.height / float(self.lengthRamp)
                self.resizeCanvases(self.height)
                # self.guiRamp = guiRamp
                if self.labels is not None:
                    self.adjustGuiLabels(self.lengthRamp)
                self.drawRampCanvases(drawRamp=drawRamp)

        # Update the OpenGL ramp
        self.ogl_cmw.ramp = deepCopySeq(self.guiRamp)
        self.ogl_cmw.tkRedraw()

        if self.continuousUpdate.get():
            self.configureCmap(cfgCmap=cfgCmap)

    def configure(
        self,
        name=None,
        ramp=None,
        geoms=None,
        legend=None,
        labels=None,
        mini="not passed",
        maxi="not passed",
        viewer=None,
        updateGui=True,
        pushRamp=True,
        **kw
    ):
        # print "ColorMapGUI.configure", mini, maxi
        ColorMap.configure(
            self, name=name, ramp=ramp, labels=labels, mini=mini, maxi=maxi
        )

        if ramp is not None:
            ramp = self.ramp
        if labels is not None:
            labels = self.labels  # because it was just set in the configure

        self.configureGui(
            ramp=ramp,
            labels=labels,
            geoms=geoms,
            legend=legend,
            viewer=viewer,
            updateGui=updateGui,
            pushRamp=pushRamp,
            **kw
        )

    def configureGui(
        self,
        name=None,
        ramp=None,
        labels=None,
        geoms=None,
        legend=None,
        viewer=None,
        updateGui=True,
        pushRamp=True,
        # guiRamp=None,
        theGivenRampIsTheGuiRamp=False,
        **kw
    ):
        """Configure the colormapGui with the given values."""
        if (ramp is not None) and (theGivenRampIsTheGuiRamp is False):
            # The ramp is new put has not been pushed onto the history
            # stack yet
            self.currentOnStack = False
            # When pushRamp is True this new ramp is pushed on the stack
            if pushRamp:
                self.pushRamp()

        if labels is not None and self.labels is not None:
            # print "labels", labels
            # import traceback;traceback.print_stack()
            self.labelsComboBox.delete(0, "end")
            for label in labels:
                self.labelsComboBox.insert(0, str(label))

        if geoms is not None and len(geoms):
            self.geoms.update(geoms)
        if viewer is not None and viewer != self.viewer:
            self.SetViewer(viewer)
            if self.name != self.legend.name:
                self.nameVar.set(self.legend.name)
                self.rename_cb()
        # if a legend is specified then set self.legend
        if legend is not None:
            self.legend = legend

        # Then update the legend with the given values
        if self.legend is not None:
            cmlOptions = {"ramp": self.ramp}

            # Need to update the legendValues as well
            cmlOptions["mini"] = self.mini
            cmlOptions["maxi"] = self.maxi

            if hasattr(self, "showLegendVar"):
                cmlOptions["visible"] = self.showLegendVar.get()
            self.legend.Set(*(), **cmlOptions)

        if updateGui:
            self.update(
                ramp=ramp,
                mini=self.mini,
                maxi=self.maxi,
                cfgCmap=False,
                theGivenRampIsTheGuiRamp=theGivenRampIsTheGuiRamp,
            )

    def Map(self, values, mini="not passed", maxi="not passed"):

        col = ColorMap.Map(self, values, mini=mini, maxi=maxi)

        if self.legend is not None:
            cmlOptions = {"ramp": self.ramp}

            # Need to update the legendValues with the value that where just used
            cmlOptions["mini"] = self.lastMini
            cmlOptions["maxi"] = self.lastMaxi

            if hasattr(self, "showLegendVar"):
                cmlOptions["visible"] = self.showLegendVar.get()
            self.legend.Set(*(), **cmlOptions)

        return col

    def configureCmap(self, cfgCmap=True):
        """This method configures the associated cmap with the GUI new values."""
        if self.cmapCompToReset is not None:
            self.resetComp(self.cmapCompToReset)
            self.cmapCompToReset = None
            cfgCmap = False
            self.cmapCurrent = True

        if self.cmapResetAll is True:
            self.reset()
            self.cmapResetAll = False
            cfgCmap = False
            self.cmapCurrent = True

        if self.nbStepBack != 0:
            if self.nbStepBack == len(self.history):
                cfgCmap = False
                self.cmapCurrent = True
            self.popRamp(-self.nbStepBack)
            self.nbStepBack = 0

        if cfgCmap:
            #            if self.allowRename:
            #                name = self.nametk.get()
            #            else:
            #                name=None

            # donnot update the cmap if already current...
            if self.cmapCurrent:
                ramp = None
            else:
                ramp = deepCopySeq(self.guiRamp)
            self.configure(ramp=ramp, mini=self.guiMini, maxi=self.guiMaxi)

            if self.legend is not None:
                if self.legend.viewer:
                    self.tk.call(self.legend.viewer.currentCamera._w, "makecurrent")
                    self.legend.RedoDisplayList()
                    self.legend.viewer.Redraw()

            self.cmapCurrent = True

        if self.labels is not None:
            self.labels = deepCopySeq(self.guiLabels)
            # print "self.labels", self.labels

        # Then will call the callbacks with the new cmap values.
        self.callCallbacks()

    def drawRampCanvases(self, event=None, drawRamp=True):
        """draw all ramp canvases"""
        # print "drawRampCanvases"
        # update Ramp

        self.currentHue = list(range(self.lengthRamp))
        self.currentSat = list(range(self.lengthRamp))

        if drawRamp:
            for v in self.idList:
                self.deleteCanvasLines(v)
                self.setRightXVals(v)
            var = self.currentCanvasVar.get()
            self.currentValues = self.rightXVals[var]
            self.drawHue()
            self.drawSaturation()
            self.drawValue()
            self.drawOpacity()

    #################################################################
    ### MOUSE CALLBACKS
    #################################################################
    def mouseUp(self, event=None):
        self.cmapCurrent = False
        self.update(drawRamp=False)

    def mouseDown(self, event):
        j = self.canvasStart
        # canvas x and y take the screen coords from the event and translate
        # them into the coordinate system of the canvas object
        Y = min(j + self.height - 1, event.y)
        x = min(self.width, event.x)
        x = max(self.xoffset, x)
        if Y < j:
            Y = j
        y = int((Y - j) / self.linesPerRampValue)
        if y < 0:
            y = 0
        self.startx = x
        self.startY = Y
        self.starty = y
        self.updateCurTk(event)
        c = self.currentCanvas
        lineIndex = self.lengthRamp - 1 - y
        line = self.currentLines[lineIndex]
        col, graybitmap = self.getColor(x, lineIndex)  # y
        newline = c.create_rectangle(
            j,
            y * self.linesPerRampValue + j,
            1 + x,  # +j,
            (1 + y) * self.linesPerRampValue + j,
            outline="",
            fill=col,
            stipple=graybitmap,
        )
        self.currentLines[lineIndex] = newline
        # update self.guiRamp
        self.updateRGBMap(x, lineIndex)
        # update rightXVals
        self.currentValues[lineIndex] = x
        c.delete(line)

    def mouseMotion(self, event):
        j = self.canvasStart
        # canvas x and y take the screen coords from the event and translate
        # them into the coordinate system of the canvas object
        # x,y are float
        # x = self.canvasHue.canvasx(event.x)
        # y = self.canvasHue.canvasy(event.y)
        # event.x, event.y are same as x,y but int
        Y = min(j + self.height - 1, event.y)
        x = min(self.width, event.x)
        x = max(self.xoffset, x)
        if Y < j:
            Y = j
        y = int((Y - j) / self.linesPerRampValue)
        if y < 0:
            y = 0
        elif self.startx is None:
            self.mouseDown(event)
        c = self.currentCanvas
        if self.startY == Y:
            lineIndex = self.lengthRamp - 1 - y
            # print "lineIndex 0 ...", lineIndex
            line = self.currentLines[lineIndex]
            col, graybitmap = self.getColor(x, lineIndex)
            newline = c.create_rectangle(
                j,
                y * self.linesPerRampValue + j,
                1 + x,  # +j,
                (1 + y) * self.linesPerRampValue + j,
                outline="",
                fill=col,
                stipple=graybitmap,
            )
            self.currentLines[lineIndex] = newline
            c.delete(line)
            self.currentValues[lineIndex] = x
            self.updateRGBMap(x, lineIndex)
        else:  # we need to interpolate for all y's between self.starty and y
            dx = x - self.startx
            dy = Y - self.startY
            rat = float(dx) / float(dy)
            if Y > self.startY:
                for Yl in range(self.startY, Y + 1):
                    yl = int((Yl - j) / self.linesPerRampValue)
                    ddx = int(rat * (Yl - self.startY)) + self.startx
                    lineIndex = self.lengthRamp - 1 - yl
                    # print "lineIndex 1 ...", lineIndex
                    line = self.currentLines[lineIndex]
                    col, graybitmap = self.getColor(ddx, lineIndex)
                    newline = c.create_rectangle(
                        j,
                        yl * self.linesPerRampValue + j,
                        1 + ddx,  # +j,
                        (yl + 1) * self.linesPerRampValue + j,
                        outline="",
                        fill=col,
                        stipple=graybitmap,
                    )
                    self.currentLines[lineIndex] = newline
                    c.delete(line)
                    self.currentValues[lineIndex] = ddx
                    self.updateRGBMap(ddx, lineIndex)
            else:
                for Yl in range(self.startY, Y - 1, -1):
                    yl = int((Yl - j) / self.linesPerRampValue)
                    ddx = int(rat * (Yl - self.startY)) + self.startx
                    lineIndex = self.lengthRamp - 1 - yl
                    # print "lineIndex 2 ...", lineIndex
                    line = self.currentLines[lineIndex]
                    col, graybitmap = self.getColor(ddx, lineIndex)
                    newline = c.create_rectangle(
                        j,
                        yl * self.linesPerRampValue + j,
                        1 + ddx,  # +j,
                        (1 + yl) * self.linesPerRampValue + j,
                        outline="",
                        fill=col,
                        stipple=graybitmap,
                    )
                    self.currentLines[lineIndex] = newline
                    c.delete(line)
                    self.currentValues[lineIndex] = ddx
                    self.updateRGBMap(ddx, lineIndex)
            self.startY = Y
            self.startx = x
            # this flushes the output, making sure that
            # the rectangle makes it to the screen
            # before the next event is handled
        self.update_idletasks()
        self.updateCurTk(event)

    def mouseDownRight(self, event):
        j = self.canvasStart
        Y = min(j + self.height - 1, event.y)
        x = min(self.width, event.x)
        x = max(self.xoffset, x)
        if Y < j:
            Y = j
        y = int((Y - j) / self.linesPerRampValue)
        if y < 0:
            y = 0
        self.startx = x
        self.startY = Y
        self.starty = y

    def mouseMotionRight(self, event):
        j = self.canvasStart
        Y = min(j + self.height - 1, event.y)
        x = min(self.width, event.x)
        x = max(self.xoffset, x)
        if Y < j:
            Y = j
        y = int((Y - j) / self.linesPerRampValue)
        if y < 0:
            y = 0
        elif self.startx is None:
            self.mouseDown(event)
        c = self.currentCanvas
        if self.straightLine is not None:
            c.delete(self.straightLine[0])
            c.delete(self.straightLine[1])

        dy = Y - self.startY
        if abs(dy) < (self.linesPerRampValue / 2):
            return

        straightLineBlack = c.create_line(
            self.startx,  # +j,
            (self.starty + 0.5) * self.linesPerRampValue + j,
            x,  # +j,
            (y + 0.5) * self.linesPerRampValue + j,
            fill="black",
            width=3,
        )
        straightLineWhite = c.create_line(
            self.startx,  # +j,
            (self.starty + 0.5) * self.linesPerRampValue + j,
            x,  # +j,
            (y + 0.5) * self.linesPerRampValue + j,
            fill="white",
            width=1,
        )
        self.straightLine = [straightLineBlack, straightLineWhite]
        self.update_idletasks()
        self.updateCurTk(event)

    def mouseUpRight(self, event=None):
        j = self.canvasStart
        c = self.currentCanvas
        if self.straightLine is not None:
            c.delete(self.straightLine[0])
            c.delete(self.straightLine[1])
        Y = min(j + self.height - 1, event.y)
        x = min(self.width, event.x)
        x = max(self.xoffset, x)
        if Y < j:
            Y = j
        y = int((Y - j) / self.linesPerRampValue)
        if y < 0:
            y = 0
        elif self.startx is None:
            self.mouseDown(event)
        dx = x - self.startx
        dY = Y - self.startY
        dy = y - self.starty
        if abs(dY) < (self.linesPerRampValue / 2):
            return
        rat = float(dx) / float(dy)
        if y > self.starty:
            for yl in range(self.starty, y + 1):
                ddx = int(rat * (yl - self.starty)) + self.startx
                lineIndex = self.lengthRamp - 1 - yl
                line = self.currentLines[lineIndex]
                col, graybitmap = self.getColor(ddx, lineIndex)
                newline = c.create_rectangle(
                    j,
                    yl * self.linesPerRampValue + j,
                    1 + ddx,  # +j,
                    (yl + 1) * self.linesPerRampValue + j,
                    outline="",
                    fill=col,
                    stipple=graybitmap,
                )
                self.currentLines[lineIndex] = newline
                c.delete(line)
                self.currentValues[lineIndex] = ddx
                self.updateRGBMap(ddx, lineIndex)
        else:
            for yl in range(self.starty, y - 1, -1):
                ddx = int(rat * (yl - self.starty)) + self.startx
                lineIndex = self.lengthRamp - 1 - yl
                line = self.currentLines[lineIndex]
                col, graybitmap = self.getColor(ddx, lineIndex)
                newline = c.create_rectangle(
                    j,
                    yl * self.linesPerRampValue + j,
                    1 + ddx,  # +j,
                    (yl + 1) * self.linesPerRampValue + j,
                    outline="",
                    fill=col,
                    stipple=graybitmap,
                )
                self.currentLines[lineIndex] = newline
                c.delete(line)
                self.currentValues[lineIndex] = ddx
                self.updateRGBMap(ddx, lineIndex)
        self.starty = y
        self.startY = Y
        self.startx = x
        # this flushes the output, making sure that
        # the rectangle makes it to the screen
        # before the next event is handled
        self.update_idletasks()
        self.updateCurTk(event)
        self.cmapCurrent = False
        self.update(drawRamp=False)

    ###########################################################################
    ##   CALLBACK FUNCTIONS
    ###########################################################################
    def apply_cb(self, event=None, cfgCmap=True):
        """"""
        # print "ColorMapGUI apply_cb"
        # Need to set self.guiMini, self.guiMaxi,from, to, from fill and to fill
        # to be set to the proper values.

        # Method which reconfigures the colormap associated to the gui
        self.configureCmap()

    def fileOpenAsk(self, idir=None, ifile=None, types=None, title="Open"):
        if types == None:
            types = [("All files", "*")]
        file = tkinter.filedialog.askopenfilename(
            filetypes=types, initialdir=idir, initialfile=ifile, title=title
        )
        if file == "":
            file = None
        return file

    def fileSaveAsk(self, idir=None, ifile=None, types=None, title="Save"):
        if types == None:
            types = [("All files", "*")]
        file = tkinter.filedialog.asksaveasfilename(
            filetypes=types, initialdir=idir, initialfile=ifile, title=title
        )
        if file == "":
            file = None
        return file

    def button_cb(self, event=None):
        """call back function for the buttons allowing to toggle between
        different canvases.
        This function hides the currentCanvas and shows the canvas
        corresponding to the active radio button.
        In addition it sets
             self.currentCanvas : used to hide it next time we come in
             self.currentLines : list of Canvas Line objects (one per canvas)
             self.currentValues : list of numerical rightXVals (one per canvas)
             self.getColor =  function to be called to represent a color as a
                              Tk string
        """
        var = self.currentCanvasVar.get()

        if var == "Hue":
            self.drawHue()
        elif var == "Sat":
            self.drawSaturation()
        elif var == "Val":
            self.drawValue()
        elif var == "Opa":
            self.drawOpacity()

        newCanvas = self.canvas[var]
        self.currentCanvas.forget()
        newCanvas.pack(side="top")
        self.currentCanvas = newCanvas
        self.currentLines = self.lines[var]
        self.currentValues = self.rightXVals[var]
        self.getColor = self.getColorFunc[var]
        self.current = var

    def min_cb(self, event=None):
        minVal = self.minTk.get()
        try:
            minVal = float(minVal)
            if self.guiMaxi is not None and minVal >= self.guiMaxi:
                raise ValueError
            self.update(mini=minVal)
        except:
            self.minTk.set("")
            self.guiMini = None
            return

    def max_cb(self, event=None):
        maxVal = self.maxTk.get()
        try:
            maxVal = float(maxVal)
            if self.guiMini is not None and maxVal <= self.guiMini:
                raise ValueError
            self.update(maxi=maxVal)
        except:
            self.maxTk.set("")
            self.guiMaxi = None
            return

    def rename_cb(self, event=None):
        self.name = self.nameVar.get()
        self.update(cmapName=self.name)
        self.legend.Set(name=self.name)
        if self.legend.ownGui is not None:
            self.legend.ownGui.title(self.legend.name)
        if self.viewer is not None:
            self.viewer.Redraw()

    def quit(self):
        # print "quit"
        self.master.destroy()

    def dismiss(self):
        # print "dismiss"
        if self.master.winfo_ismapped():
            self.master.withdraw()

    def resetAll_cb(self, event=None):
        self.cmapResetAll = True
        self.update(ramp=deepCopySeq(self.history[0]), cfgCmap=False)

    #    def reset_cb(self, event=None):
    #        """reset only the currently visible property canvas"""
    #        var = self.currentCanvasVar.get()
    #        self.deleteCanvasLines(var)
    #        ramp = deepCopySeq(self.history[0])
    #
    #        self.lengthRamp = len(ramp)
    #        if self.lengthRamp > self.height :
    #            self.height = self.lengthRamp
    #        self.numOfRampValues.set( self.lengthRamp )
    #
    #        hsva = map(lambda x, conv=RGBA2HSLA_list: conv(x), ramp)
    #        ind = self.idList.index(var)
    #        #format?...list?....array??
    #        newVals = Numeric.array(hsva)[:,ind]
    #        self.guiRamp = self.buildRGBMap(ind, newVals)
    #
    #        self.cmapCompToReset = var
    #        if var == 'Hue':
    #            self.setRightXVals('Hue')
    #            self.drawHue()
    #        elif var == 'Sat':
    #            self.setRightXVals('Sat')
    #            self.drawSaturation()
    #        elif var == 'Val':
    #            self.setRightXVals('Val')
    #            self.drawValue()
    #        elif var == 'Opa':
    #            self.setRightXVals('Opa')
    #            self.drawOpacity()
    #        if self.continuousUpdate.get():
    #            self.configureCmap()
    #        #self.mouseUp(None) # to call callbacks
    #        self.currentValues = self.rightXVals[var]
    #        self.ogl_cmw.ramp = self.guiRamp[:]
    #        self.ogl_cmw.tkRedraw()

    def stepBack_cb(self):
        # update self.ramp to last ramp on history list
        if len(self.history) == 1 and self.cmapCurrent is True:
            return

        if self.cmapCurrent and self.nbStepBack == 0:
            index = self.nbStepBack + 2
        else:
            index = self.nbStepBack + 1

        self.nbStepBack = index
        newind = len(self.history) - index
        cfgCmap = True

        if newind < 0:
            # tried to go back too far
            newind = 0
            self.nbStepBack = 0

        if newind == 0:
            # only valid for continuous mode.
            # want to go back to the first entry of the history which
            # stays so we don't need to update the cmap
            cfgCmap = False
        self.update(ramp=self.history[newind], cfgCmap=cfgCmap)

    def read_cb(self):
        fileTypes = [("ColorMap", "*_map.py"), ("any file", "*.*")]
        fileBrowserTitle = "Read Color Map"
        fileName = self.fileOpenAsk(types=fileTypes, title=fileBrowserTitle)
        if not fileName:
            return

        self.read(fileName)

    def read(self, filename):

        ColorMap.read(self, filename)
        self.configureGui(ramp=self.ramp, mini=self.mini, maxi=self.maxi)

        if self.legend.viewer:
            # self.legend.RedoDisplayList()
            self.legend.viewer.Redraw()
            # self.configureCmap()

    def enter_cb(self, event=None):
        if widgetsOnBackWindowsCanGrabFocus is False:
            lActiveWindow = self.focus_get()
            if lActiveWindow is not None and (
                lActiveWindow.winfo_toplevel() != self.winfo_toplevel()
            ):
                return

        self.focus_set()

    def leave_cb(self, event=None):
        pass

    ############################################################
    ### UTILITY FUNCTIONS
    ############################################################
    def makeEvent(self, x, y):
        xval = x * self.xrange + self.xoffset
        return DummyEvent(xval, y)

    def hueColor(self, val, rampIndex):
        """TkColorString <- hueColor(val)
        val is an integer between self.xoffset and self.width.
        (default:val is an integer between 25 and 200.)
        returns color to be use to draw hue lines in hue canvas"""
        # print "hueColor", h
        if val > self.width:
            h = 1
        else:
            h = float(self.width - val) / self.xrange  # * .999 #*.6666666667
        #        if h == 0:
        #            h = 1
        self.currentHue[rampIndex] = h
        rgb = HSL2RGB(h, 1.0, 0.5)
        graybitmap = ""
        return TkColor(rgb), graybitmap

    def satColor(self, val, rampIndex):
        """TkColorString <- satColor(val)
        val is an integer between self.xoffset and self.width.
        (default:val is an integer between 25 and 200.)
        returns color to be use to draw saturation lines in saturation canvas"""
        # print "satColor", val, rampIndex
        if val < self.xoffset:
            x = 0
        else:
            x = float(val - self.xoffset) / self.xrange
        self.currentSat[rampIndex] = x
        rgb = HSL2RGB(self.currentHue[rampIndex], x, 0.5)
        rgb.append(1.0)
        graybitmap = ""
        return TkColor(rgb), graybitmap

    def valColor(self, val, rampIndex):
        """TkColorString <- valColor(val)
        val is an integer between 25 and 200
        returns color to be used to draw value and opacity lines in canvas"""
        # print "valColor", val, rampIndex
        if val < self.xoffset:
            x = 0
        else:
            x = float(val - self.xoffset) / self.xrange
        rgb = HSL2RGB(self.currentHue[rampIndex], self.currentSat[rampIndex], x)
        rgb.append(1.0)
        graybitmap = ""
        return TkColor(rgb), graybitmap

    def opaColor(self, val, rampIndex=None):
        # print "opaColor"
        if val < self.xoffset:
            x = 0
        else:
            x = float(val - self.xoffset) / self.xrange

        if x >= 1:
            graybitmap = ""
            col = "black"
        elif x > 0.75:
            graybitmap = "gray75"
            col = "black"
        elif x > 0.50:
            graybitmap = "gray50"
            col = "black"
        elif x > 0.25:
            graybitmap = "gray25"
            col = "black"
        elif x > 0:
            graybitmap = "gray12"
            col = "black"
        else:
            graybitmap = ""
            col = ""
        return col, graybitmap

    def opaColor_Unused(self, val, rampIndex=None):
        # the color of the dot changes
        # we don't use it because the limit line drawn is less visible

        x = float(val - self.xoffset) / self.xrange
        background = self.canvas["Opa"].configure()["background"]
        backgroundHSV = ToHSV(background[4], mode="HEX", flag255=0)
        bgHSV = [backgroundHSV[0], backgroundHSV[1], backgroundHSV[2] * (1 - x)]
        col = ToHEX(bgHSV, mode="HSV")
        if x >= 1:
            graybitmap = ""
        elif x > 0.75:
            graybitmap = "gray75"
        elif x > 0.50:
            graybitmap = "gray50"
        elif x > 0.25:
            graybitmap = "gray25"
        elif x > 0:
            graybitmap = "gray12"
        else:
            graybitmap = ""
        return col, graybitmap

    #    def createCMLWidget(self):
    #        self.legend_gui = Tkinter.Toplevel()
    #        self.legend_gui.title(self.legend.name)
    #        self.legend_gui.protocol('WM_DELETE_WINDOW', self.legend_gui.withdraw )
    #
    #        frame1 = Tkinter.Frame(self.legend_gui)
    #        frame1.pack(side='top')
    #
    #        #unit
    #        self.unitsEnt = Pmw.EntryField(frame1,
    #                                       label_text='Units  ',
    #                                       labelpos='w',
    #                                       command=self.updateCML_cb)
    #        self.unitsEnt.pack(side='top', fill='x')
    #
    #        #glf vector font
    #        self.glfFont = Tkinter.StringVar()
    #        self.glfFont.set('chicago1.glf')
    #        self.glfFontCB = Pmw.ComboBox(frame1, label_text='Font    ',
    #                                   labelpos='w',
    #                                   entryfield_value=self.glfFont.get(),
    #                                   scrolledlist_items=ColorMapLegend.glfVectorFontList,
    #                                   selectioncommand=self.updateCML_cb)
    #        self.glfFontCB.pack(side='top', fill='x')
    #
    #        #fontScale
    #        self.fontScale = ThumbWheel(frame1,
    #                                    labCfg={'text':'font scale            ', 'side':'left'},
    #                                    showLabel=1,
    #                                    width=90,
    #                                    height=14,
    #                                    min=0,
    #                                    max=200,
    #                                    type=int,
    #                                    value=self.legend.fontScale,
    #                                    callback=self.updateCML_cb,
    #                                    continuous=True,
    #                                    oneTurn=10,
    #                                    wheelPad=0)
    #        self.fontScale.pack(side='top')
    #
    #        #label
    #        self.labelValsEnt = Pmw.EntryField(
    #                                frame1,
    #                                label_text='Numeric labels    ',
    #                                labelpos='w',
    #                                command=self.updateCML_cb)
    #        self.labelValsEnt.component('entry').config(width=6)
    #        self.labelValsEnt.pack(side='top', fill='x')
    #
    #        #numOfLabel
    #        self.numOfLabelsCtr = ThumbWheel(frame1,
    #                                    labCfg={'text':'Automatic labels', 'side':'left'},
    #                                    showLabel=1,
    #                                    width=90,
    #                                    height=14,
    #                                    min=0,
    #                                    max=200,
    #                                    type=int,
    #                                    value=5,
    #                                    callback=self.updateCML_cb,
    #                                    continuous=True,
    #                                    oneTurn=20,
    #                                    wheelPad=0)
    #        self.numOfLabelsCtr.pack(side='top')
    #
    #        # Interpolate
    #        self.interpVar = Tkinter.IntVar()
    #        self.interpVar.set(0)
    #        self.checkBoxFrame = Tkinter.Checkbutton(
    #                                frame1,
    #                                text='Interpolate',
    #                                variable=self.interpVar,
    #                                command=self.updateCML_cb)
    #        self.checkBoxFrame.pack(side='top')
    #
    #        # frame
    #        self.frameVar = Tkinter.IntVar()
    #        self.frameVar.set(1)
    #        self.checkBoxFrame = Tkinter.Checkbutton(
    #                                frame1,
    #                                text='Frame',
    #                                variable=self.frameVar,
    #                                command=self.updateCML_cb)
    #        self.checkBoxFrame.pack(side='top')
    #
    #        # invert labels color
    #        self.invertLabelsColorVar = Tkinter.IntVar()
    #        self.invertLabelsColorVar.set(0)
    #        self.checkBoxinvertLabelsColor = Tkinter.Checkbutton(
    #                                frame1,
    #                                text='Invert labels color',
    #                                variable=self.invertLabelsColorVar,
    #                                command=self.updateCML_cb)
    #        #self.checkBoxFrame.pack(side='top')
    #        self.checkBoxinvertLabelsColor.pack(side='top')
    #
    #        # colormapguiwidget:
    #        self.launchColormapWidget = Tkinter.Button(
    #                                        frame1,
    #                                        text="Show colormap settings",
    #                                        command=self.showColormapSettings_cb )
    #        self.launchColormapWidget.pack(side='top', fill='x')

    def showColormapSettings_cb(self, event=None):
        # print "showColormapSettings_cb"
        master = self.master
        while (
            hasattr(master, "deiconify") is False and hasattr(master, "master") is True
        ):
            master = master.master
        if hasattr(master, "deiconify"):
            if master.winfo_ismapped() == 0:
                master.deiconify()
            master.lift()
            # else: master.withdraw()

    def showLegendButton_cb(self, event=None):
        # print "showLegendButton_cb"
        if not self.viewer:
            return
        if not self.legend:
            self.createCML()
        visible = self.showLegendVar.get()
        self.legend.Set(visible=visible)
        # self.legend.setWithOwnGui()

        if visible == 0:
            if self.legend.viewer.currentObject is self.legend:
                self.legend.viewer.SetCurrentObject(self.legend.viewer.rootObject)

        # do you have to do a redraw to see it?
        self.viewer.Redraw()

    def showLegend(self):
        self.showLegendVar.set(1)
        self.showLegendButton_cb()

    def hideLegend(self):
        self.showLegendVar.set(0)
        self.showLegendButton_cb()

    def editLegend_cb(self, event=None):
        # print "editLegend_cb"
        if not self.legend:
            self.createCML()
        self.legend.showOwnGui()

    def resizeCanvases(self, height=None, width=None):
        # print "resizeCanvases"
        if height is not None:
            for c in list(self.canvas.values()):
                c.configure(height=height)
            self.ogl_cmw.configure(height=height)
            self.ogl_cmw.height = height

        if width is not None:
            for c in list(self.canvas.values()):
                c.configure(width=width)
            self.ogl_cmw.configure(width=width)
            self.ogl_cmw.width = width

    def buildRGBMap(self, ind, newVals):
        """ind is 0 for Hue, 1 for Sat etc
        newVals is list of new rightXValues for that column"""
        # print "buildRGBMap"
        rgbs = []
        hsva = list(map(list, list(map(RGBA2HSLA_list, self.guiRamp))))
        for i in range(len(self.guiRamp)):
            hsva[i][ind] = newVals[i]
            rgbs.append(list(HSLA2RGBA_list(hsva[i])))
        return rgbs

    def buildRightXVals(self):
        """idList = ['Hue','Sat','Opa','Val']"""
        for id in self.idList:
            self.setRightXVals(id)

    def setRightXVals(self, idStr):
        # each canvas line is drawn at constant y value
        # between x1=0 on the left and x2 which is current
        # ramp at y (which ranges between 0. and 1.) times 175
        # NB: 175 is the effective width of the canvas
        # idList = ['Hue','Sat','Opa','Val']

        # print "setRightXVals"

        if idStr not in self.idList:
            return
        ind = self.idList.index(idStr)
        # apparently these are 200-this value and
        # for entire Hue ramp delta x = .66401
        hsvaRamp = list(map(list, list(map(RGBA2HSLA_list, self.guiRamp))))
        ramp_vals = Numeric.array(hsvaRamp)[:, ind]
        norm_n = ramp_vals
        if idStr == "Hue":
            # self.width is 200 which is 25 border + 175 map
            # 25 and 175 are the default values but can be changed
            val = self.width - (norm_n * self.xrange)
        else:
            val = norm_n * self.xrange + self.xoffset
        # self.rightXVals[idStr] = map(int, val.tolist())
        self.rightXVals[idStr] = val.tolist()

    def write_cb(self):
        fileTypes = [("ColorMap", "*_map.py"), ("any file", "*.*")]
        fileBrowserTitle = "Write Color Map"
        fileName = self.fileSaveAsk(types=fileTypes, title=fileBrowserTitle)
        if not fileName:
            return
        self.write(fileName)

    def deleteCanvasLines(self, name):
        """delete all lines in ramp canvas"""
        assert name in self.idList
        # assert name in ['Hue', 'Sat', 'Val', 'Opa' ]
        l = self.lines[name]
        c = self.canvas[name]
        for i in range(len(l)):
            c.delete(l[i])
        self.lines[name] = []
        self.rightXVals[name] = []
        self.curxTk.set("0.0")
        self.curyTk.set("0.0")
        if self.current == name:
            self.currentValues = self.rightXVals[name]
            self.currentLines = self.lines[name]

    def drawHue(self):
        j = self.canvasStart
        # print "drawHue"
        # this is for initializing and resets
        l = self.lines["Hue"]
        c = self.canvas["Hue"]
        v = self.rightXVals["Hue"]

        for i in range(len(l)):
            c.delete(l[i])
        self.lines["Hue"] = []
        l = self.lines["Hue"]

        for i in range(self.lengthRamp):
            # nb val is the LENGTH of the line to draw
            val = v[i]
            col, graybitmap = self.hueColor(val, i)
            l.append(
                c.create_rectangle(
                    j,
                    (self.lengthRamp - 1 - i) * self.linesPerRampValue + j,
                    1 + val,
                    ((self.lengthRamp - 1 - i) + 1) * self.linesPerRampValue + j,
                    fill=col,
                    outline="",
                )
            )

        if self.current == "Hue":
            self.currentLines = l

    def drawSaturation(self):
        # print "drawSaturation"
        c = self.canvas["Sat"]
        l = self.lines["Sat"]
        v = self.rightXVals["Sat"]
        j = self.canvasStart

        for i in range(len(l)):
            c.delete(l[i])
        self.lines["Sat"] = []
        l = self.lines["Sat"]

        for i in range(self.lengthRamp):
            val = v[i]
            col, graybitmap = self.satColor(val, i)
            l.append(
                c.create_rectangle(
                    j,
                    (self.lengthRamp - 1 - i) * self.linesPerRampValue + j,
                    1 + val,
                    ((self.lengthRamp - 1 - i) + 1) * self.linesPerRampValue + j,
                    fill=col,
                    outline="",
                )
            )
        if self.current == "Sat":
            self.currentLines = l

    def drawValue(self):
        c = self.canvas["Val"]
        l = self.lines["Val"]
        v = self.rightXVals["Val"]
        j = self.canvasStart

        for i in range(len(l)):
            c.delete(l[i])
        self.lines["Val"] = []
        l = self.lines["Val"]

        for i in range(self.lengthRamp):
            val = v[i]
            col, graybitmap = self.valColor(val, i)
            # print "val i col", val, i, col
            l.append(
                c.create_rectangle(
                    j,
                    (self.lengthRamp - 1 - i) * self.linesPerRampValue + j,
                    1 + val,
                    ((self.lengthRamp - 1 - i) + 1) * self.linesPerRampValue + j,
                    fill=col,
                    outline="",
                )
            )
        if self.current == "Val":
            self.currentLines = l

    def drawOpacity(self):
        c = self.canvas["Opa"]
        l = self.lines["Opa"]
        v = self.rightXVals["Opa"]
        j = self.canvasStart

        for i in range(len(l)):
            c.delete(l[i])
        self.lines["Opa"] = []
        l = self.lines["Opa"]

        for i in range(self.lengthRamp):
            val = v[i]
            col, graybitmap = self.opaColor(val)
            l.append(
                c.create_rectangle(
                    j,
                    (self.lengthRamp - 1 - i) * self.linesPerRampValue + j,
                    1 + val,
                    ((self.lengthRamp - 1 - i) + 1) * self.linesPerRampValue + j,
                    outline="",
                    fill=col,
                    stipple=graybitmap,
                )
            )
        if self.current == "Opa":
            self.currentLines = l

    def addCallback(self, function):
        assert hasattr(function, "__call__")
        self.callbacks.append(function)

    def callCallbacks(self):
        for f in self.callbacks:
            f(self)

    def valueAtY(self, y):
        # compute the value for q given line in canvas
        y = y - self.canvasStart
        y = max(y, 0)
        y = min(y, self.height - 1)
        if self.guiMini is not None and self.guiMaxi is not None:
            range = self.guiMaxi - self.guiMini
            return (float(self.height - y) / (self.height - 1)) * range + self.guiMini
        else:
            return int((self.height - y) / self.linesPerRampValue)

    def indexAtY(self, y):
        # compute the value for q given line in canvas
        j = self.canvasStart
        Y = min(j + self.height - 1, y)
        if Y < j:
            Y = j
        y = int((Y - j) / self.linesPerRampValue)
        return y

    def updateCurTk(self, event):
        x = event.x  # - self.canvasStart
        x = max(x, self.xoffset)
        x = min(x, self.width)
        val = (x - self.xoffset) / self.xrange
        self.curxTk.set("%4.2f" % val)
        lVal = self.valueAtY(event.y)
        if lVal is not None:
            self.curyTk.set("%4.2f" % lVal)
        else:
            self.curyTk.set("")
        if self.labels is not None:
            self.labelsComboBox.selectitem(self.indexAtY(event.y))

    def updateOGLwidget(self):
        self.ogl_cmw.tkRedraw()

    def updateRGBMap(self, x, y):

        cur_val = list(RGBA2HSLA_list(self.guiRamp[y]))
        cur_val[0] = self.currentHue[y]
        cur_val[1] = self.currentSat[y]

        if self.current == "Hue":
            h = ((self.width - x) / self.xrange) * 0.999  # *.6666666667
            cur_val[0] = round(h, 3)
        else:
            # use keyList = ['Sat', 'Val', 'Opa']
            keyList = self.idList[1:]
            ind = keyList.index(self.current) + 1
            h = (x - self.xoffset) / self.xrange
            cur_val[ind] = round(h, 3)
        self.guiRamp[y] = list(HSLA2RGBA_list(cur_val))


class OGLColorMapWidget(OGLWidget):
    """This object provides a OpenGL window that displays an RGBA color map"""

    def __init__(
        self,
        master,
        cmap,
        title="OGLColorMapWidget",
        width=None,
        height=None,
        cnf=None,
        **kw
    ):

        if width is None:
            kw["width"] = 19
        else:
            kw["width"] = width
        if height is None:
            kw["height"] = 180
        else:
            kw["height"] = height

        self.callback = None

        assert isinstance(cmap, ColorMap)
        self.ramp = deepCopySeq(cmap.ramp)
        self.step = 1  # set to larger values to accelerate redraw

        tf = self.topFrame = tkinter.Frame(master, borderwidth=1)
        self.frame = tkinter.Frame(tf, borderwidth=3, relief="sunken")

        if cnf is None:
            cnf = {}
        OGLWidget.__init__(*(self, self.frame, title, cnf, 0), **kw)

        self.frame.pack(expand=1, fill="both")
        self.topFrame.pack(expand=1, fill="both")
        self.pack(side="left", expand=1, fill="both")
        # self.initTexture()

    def tkRedraw(self, *dummy):
        """guillaume: probably useless, the code is almost identical
        in the overriden function OGLWidget.tkRedraw"""
        self.update_idletasks()
        self.tk.call(self._w, "makecurrent")
        self.initProjection()
        GL.glPushMatrix()
        self.redraw(*dummy)  # guillaume: self.redraw() in OGLWidget.tkRedraw
        GL.glFlush()
        GL.glPopMatrix()
        self.tk.call(self._w, "swapbuffers")

    def redraw(self, line=None):
        # print "redraw"
        drawLegendOnly(
            fullWidth=self.width,
            fullHeight=self.height,
            ramp=self.ramp,
            verticalLegend=True,
            roomLeftToLegend=0,
            roomBelowLegend=0,
            legendShortSide=self.width,
            legendLongSide=self.height,
            interpolate=False,
            selected=False,
        )
        return


if __name__ == "__main__":
    # import pdb

    # test = ColorMapGUI()
    # def cb(ramp, min, max):
    # print len(ramp), min, max
    # test.addCallback(cb)

    ##cm = ColorMap('cmap', filename='/home/rhuey/python/dev/rgb.map')
    # cmg = ColorMapGUI(cm, allowRename=1)

    l = {}
    g = {}
    exec(
        compile(open("Tests/rgb256_map.py").read(), "Tests/rgb256_map.py", "exec"), g, l
    )
    cm = None
    # for name, object in l.items():
    #    if isinstance(object, ColorMap):
    #        cm = object
    #        break
    cm = l["cm"]

    from DejaVu import Viewer

    vi = Viewer()
    cmg = ColorMapGUI(cm, allowRename=1, viewer=vi)

# test.mainloop()

## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: <NAME> # # Copyright: <NAME> TSRI 2000 # # Revision: <NAME> # ############################################################################# # # $Header$ # # $Id$ # # from string import strip, split, find # print "_addHistory" dummy Tkinter event The ColorMapGUI is an object providing an interface to expose     and to modify a ColorMap object.      The ColorMapGUI has a local copy of the colormap.ramp, colormap.mini and     colormap.maxi which will be modified through the GUI.     The associated colormap object will only be updated when by the apply_cb     which is called whenever a mouseUp event or update is called if the gui     is in continuous mode or when the Aplly button is pressed when the gui is     not in a continuous mode.      The GUI allows the user to edit each of 4 different color     properties: 'Hue','Sat' or saturation, 'Val' or value     and 'Opa' or opacity for each entry in the ramp of the     ColorMap. This is implemented via 4 Canvases, one for     each color property. (Drawing on a canvas is done by     pressing the left mouse button over the canvas and     holding it down while moving the mouse.)     Drawing at a point 'x','y', on one of the canvases changes     the value of the corresponding color property in this way:     'y' specifies the entry in the ColorMap.ramp to be changed.     'x' is first normalized to give a value between 0 and 1.0.     (by dividing it by the effective canvas width).     A new rgba value is built from the hsva list comprised of     3 previous values and this new normalized 'x' in the     appropriate position. (that is, if the user is drawing on     the 'Hue' canvas, the normalized 'x' value replaces the 'h',     or zeroth entry,etc).      If the GUI has a viewer, an OpenGLColorMapWidget is constructed     which displays the GUI's current rgbMap. Also, the user can choose     to add a ColorMapLegend to the viewer which displays the current     ColorMap.ramp and which can be labeled. # this is the active colormap # initialize a bunch of flags. # Initialize the local guiRamp, guiMini and guiMaxi values # which will be modified # Create parts of the GUI # we hide it if it was asked # Canvas width (default=200) # left border width (default=25) # Available drawing width default=width-xoffset # DejaVu viewer to which colorMapLegend is added # if allowRename is False, name entry is disabled. # initialize dictionaries # NB all the lines end at xpoints corresponding to the # the colorproperty value at that point... (except #'Hue' is backwards, width-property+xoffset instead of # property+xoffset) # name of the currently visible prop. canvas # list of functions to be called when apply # button is pressed or ramp is modified and # mode is continuous update # Calls the createWidgets method to create the 4 canvases # and the buttons. # Call the update to initialize the gui with the given cmap values, # without configuring the cmap # set current colorFunc, lines and values to 'Hue' # set-up canvas mouse bindings: # create the cml #        # fields created by the CMLwidget #        self.legend.createOwnGui() #        self.legend.hideOwnGui() # Tkinter.Widget.bind(master2, '<Configure>', self.configure_cb) # print "configure_cb", event, dir (event) # print "configure_cb event.height", event.height #        self.width = event.width #        self.xrange = float(self.width - self.xoffset) # sys.platform == 'win32': # print "configure_cb height", height # print "self.height 1", self.height # print "changeRampLength_cb", numOfRampValue, len(self.guiRamp), len(self.ramp) # import traceback;traceback.print_stack() # numOfRampValue > lenguiramp: # guiRamp=self.guiRamp # print "adjustGuiLabels", newNumOfGuiLabels create the ColorMap Legend # width defaults to len(ramp); height defaults to 1 # mini, maxi and interp set from self #    def resetComp(self, comp): #        """resets on component to first entry in history list""" #        compNum = ['Hue','Sat','Val','Opa'].index(comp) #        # Get the first entry in the history list #        hist = self.history[0] #        # Remove all the entries in the history list #        self.history = self.history[:1] # #        # Transform the history RGBramp into a HSL ramp #        histHSL = map(lambda x: list(RGBA2HSLA_list(x)), hist) #        # Transform the current ramp in a HSL ramp #        hsl = map(lambda x: list(x), self.asHSL()) #        for i in range(len(hsl)): #            hsl[i][compNum] = histHSL[i][compNum] #        ramp = map(lambda x: list(HSLA2RGBA_list(x)), hsl) #        self.configure(ramp=ramp, updateGui=False) return to first entry in history list The pushRamp method appends the current ramp stored in cmap.ramp at the         end of the history list.         The attribute self.currentOnStack is set to True. # append the current ramp to the history if the ramp is not None and # if the ramp has not been pushed onto the history stack yet. optional arguments         index -- default -1, specifies the index of the ramp to pop.                  It is a negative index                  as we are popping ramps from the end of the history list.          The popRamp method will save the ramp stored at the given index         in cmap.ramp then remove all the entry from the ramp (included)         till the end of the history list.         After a popRamp the attribute self.currentOnStack is False. # Need at least one entry in the history # Always keep the first entry of the history # PopRamp removes entry from the end of the history list # which is why the index has to be negative. # 1- set the actual ramp to be the entry of history # corresponding to the given index # 2- history = history[:index] # the popped history is not on the stack any longer except # when it is the first entry # Get the index from the beginning of the history list # Always keep the first entry in the history list # We do not want to push the ramp we are popping onto the history stack # the current ramp will not be on the history stack any longer. to give a viewer reference to the ColorMapGUI even         after it's creation # self.legend.protected = True create Tkinter widgets: 4 canvas and buttons in 2 frames # print "createWidgets" # create menu frame ##         editmenu.add_checkbutton(label='Preview', variable=self.preview) # create canvas frames # create a frame for rproperties canvases # create 4 canvases # pack Hue to start with # create a frame for buttons # create radio buttons to switch between canvas # pack(side='left') # pack(side='left') # pack(side='left') # pack(side='left') # name # min max # self.labelsInComboBox = Tkinter.StringVar() # Apply and Dismiss go here # guiRamp=None # Update the name of cmg if relevant # Update the maxi and mini values of cmg # Update the cmg ramp with the one given # print "self.height 2", self.height # print "guiRamp" # print "self.height 3", self.height # self.numOfRampValues.set(self.lengthRamp) # self.guiRamp = guiRamp # Update the OpenGL ramp # print "ColorMapGUI.configure", mini, maxi # because it was just set in the configure # guiRamp=None, Configure the colormapGui with the given values. # The ramp is new put has not been pushed onto the history # stack yet # When pushRamp is True this new ramp is pushed on the stack # print "labels", labels # import traceback;traceback.print_stack() # if a legend is specified then set self.legend # Then update the legend with the given values # Need to update the legendValues as well # Need to update the legendValues with the value that where just used This method configures the associated cmap with the GUI new values. #            if self.allowRename: #                name = self.nametk.get() #            else: #                name=None # donnot update the cmap if already current... # print "self.labels", self.labels # Then will call the callbacks with the new cmap values. draw all ramp canvases # print "drawRampCanvases" # update Ramp ################################################################# ### MOUSE CALLBACKS ################################################################# # canvas x and y take the screen coords from the event and translate # them into the coordinate system of the canvas object # y # +j, # update self.guiRamp # update rightXVals # canvas x and y take the screen coords from the event and translate # them into the coordinate system of the canvas object # x,y are float # x = self.canvasHue.canvasx(event.x) # y = self.canvasHue.canvasy(event.y) # event.x, event.y are same as x,y but int # print "lineIndex 0 ...", lineIndex # +j, # we need to interpolate for all y's between self.starty and y # print "lineIndex 1 ...", lineIndex # +j, # print "lineIndex 2 ...", lineIndex # +j, # this flushes the output, making sure that # the rectangle makes it to the screen # before the next event is handled # +j, # +j, # +j, # +j, # +j, # +j, # this flushes the output, making sure that # the rectangle makes it to the screen # before the next event is handled ########################################################################### ##   CALLBACK FUNCTIONS ########################################################################### # print "ColorMapGUI apply_cb" # Need to set self.guiMini, self.guiMaxi,from, to, from fill and to fill # to be set to the proper values. # Method which reconfigures the colormap associated to the gui call back function for the buttons allowing to toggle between         different canvases.         This function hides the currentCanvas and shows the canvas         corresponding to the active radio button.         In addition it sets              self.currentCanvas : used to hide it next time we come in              self.currentLines : list of Canvas Line objects (one per canvas)              self.currentValues : list of numerical rightXVals (one per canvas)              self.getColor =  function to be called to represent a color as a                               Tk string # print "quit" # print "dismiss" #    def reset_cb(self, event=None): #        """reset only the currently visible property canvas""" #        var = self.currentCanvasVar.get() #        self.deleteCanvasLines(var) #        ramp = deepCopySeq(self.history[0]) # #        self.lengthRamp = len(ramp) #        if self.lengthRamp > self.height : #            self.height = self.lengthRamp #        self.numOfRampValues.set( self.lengthRamp ) # #        hsva = map(lambda x, conv=RGBA2HSLA_list: conv(x), ramp) #        ind = self.idList.index(var) #        #format?...list?....array?? #        newVals = Numeric.array(hsva)[:,ind] #        self.guiRamp = self.buildRGBMap(ind, newVals) # #        self.cmapCompToReset = var #        if var == 'Hue': #            self.setRightXVals('Hue') #            self.drawHue() #        elif var == 'Sat': #            self.setRightXVals('Sat') #            self.drawSaturation() #        elif var == 'Val': #            self.setRightXVals('Val') #            self.drawValue() #        elif var == 'Opa': #            self.setRightXVals('Opa') #            self.drawOpacity() #        if self.continuousUpdate.get(): #            self.configureCmap() #        #self.mouseUp(None) # to call callbacks #        self.currentValues = self.rightXVals[var] #        self.ogl_cmw.ramp = self.guiRamp[:] #        self.ogl_cmw.tkRedraw() # update self.ramp to last ramp on history list # tried to go back too far # only valid for continuous mode. # want to go back to the first entry of the history which # stays so we don't need to update the cmap # self.legend.RedoDisplayList() # self.configureCmap() ############################################################ ### UTILITY FUNCTIONS ############################################################ TkColorString <- hueColor(val)         val is an integer between self.xoffset and self.width.         (default:val is an integer between 25 and 200.)         returns color to be use to draw hue lines in hue canvas # print "hueColor", h # * .999 #*.6666666667 #        if h == 0: #            h = 1 TkColorString <- satColor(val)         val is an integer between self.xoffset and self.width.         (default:val is an integer between 25 and 200.)         returns color to be use to draw saturation lines in saturation canvas # print "satColor", val, rampIndex TkColorString <- valColor(val)         val is an integer between 25 and 200         returns color to be used to draw value and opacity lines in canvas # print "valColor", val, rampIndex # print "opaColor" # the color of the dot changes # we don't use it because the limit line drawn is less visible #    def createCMLWidget(self): #        self.legend_gui = Tkinter.Toplevel() #        self.legend_gui.title(self.legend.name) #        self.legend_gui.protocol('WM_DELETE_WINDOW', self.legend_gui.withdraw ) # #        frame1 = Tkinter.Frame(self.legend_gui) #        frame1.pack(side='top') # #        #unit #        self.unitsEnt = Pmw.EntryField(frame1, #                                       label_text='Units  ', #                                       labelpos='w', #                                       command=self.updateCML_cb) #        self.unitsEnt.pack(side='top', fill='x') # #        #glf vector font #        self.glfFont = Tkinter.StringVar() #        self.glfFont.set('chicago1.glf') #        self.glfFontCB = Pmw.ComboBox(frame1, label_text='Font    ', #                                   labelpos='w', #                                   entryfield_value=self.glfFont.get(), #                                   scrolledlist_items=ColorMapLegend.glfVectorFontList, #                                   selectioncommand=self.updateCML_cb) #        self.glfFontCB.pack(side='top', fill='x') # #        #fontScale #        self.fontScale = ThumbWheel(frame1, #                                    labCfg={'text':'font scale            ', 'side':'left'}, #                                    showLabel=1, #                                    width=90, #                                    height=14, #                                    min=0, #                                    max=200, #                                    type=int, #                                    value=self.legend.fontScale, #                                    callback=self.updateCML_cb, #                                    continuous=True, #                                    oneTurn=10, #                                    wheelPad=0) #        self.fontScale.pack(side='top') # #        #label #        self.labelValsEnt = Pmw.EntryField( #                                frame1, #                                label_text='Numeric labels    ', #                                labelpos='w', #                                command=self.updateCML_cb) #        self.labelValsEnt.component('entry').config(width=6) #        self.labelValsEnt.pack(side='top', fill='x') # #        #numOfLabel #        self.numOfLabelsCtr = ThumbWheel(frame1, #                                    labCfg={'text':'Automatic labels', 'side':'left'}, #                                    showLabel=1, #                                    width=90, #                                    height=14, #                                    min=0, #                                    max=200, #                                    type=int, #                                    value=5, #                                    callback=self.updateCML_cb, #                                    continuous=True, #                                    oneTurn=20, #                                    wheelPad=0) #        self.numOfLabelsCtr.pack(side='top') # #        # Interpolate #        self.interpVar = Tkinter.IntVar() #        self.interpVar.set(0) #        self.checkBoxFrame = Tkinter.Checkbutton( #                                frame1, #                                text='Interpolate', #                                variable=self.interpVar, #                                command=self.updateCML_cb) #        self.checkBoxFrame.pack(side='top') # #        # frame #        self.frameVar = Tkinter.IntVar() #        self.frameVar.set(1) #        self.checkBoxFrame = Tkinter.Checkbutton( #                                frame1, #                                text='Frame', #                                variable=self.frameVar, #                                command=self.updateCML_cb) #        self.checkBoxFrame.pack(side='top') # #        # invert labels color #        self.invertLabelsColorVar = Tkinter.IntVar() #        self.invertLabelsColorVar.set(0) #        self.checkBoxinvertLabelsColor = Tkinter.Checkbutton( #                                frame1, #                                text='Invert labels color', #                                variable=self.invertLabelsColorVar, #                                command=self.updateCML_cb) #        #self.checkBoxFrame.pack(side='top') #        self.checkBoxinvertLabelsColor.pack(side='top') # #        # colormapguiwidget: #        self.launchColormapWidget = Tkinter.Button( #                                        frame1, #                                        text="Show colormap settings", #                                        command=self.showColormapSettings_cb ) #        self.launchColormapWidget.pack(side='top', fill='x') # print "showColormapSettings_cb" # else: master.withdraw() # print "showLegendButton_cb" # self.legend.setWithOwnGui() # do you have to do a redraw to see it? # print "editLegend_cb" # print "resizeCanvases" ind is 0 for Hue, 1 for Sat etc         newVals is list of new rightXValues for that column # print "buildRGBMap" idList = ['Hue','Sat','Opa','Val'] # each canvas line is drawn at constant y value # between x1=0 on the left and x2 which is current # ramp at y (which ranges between 0. and 1.) times 175 # NB: 175 is the effective width of the canvas # idList = ['Hue','Sat','Opa','Val'] # print "setRightXVals" # apparently these are 200-this value and # for entire Hue ramp delta x = .66401 # self.width is 200 which is 25 border + 175 map # 25 and 175 are the default values but can be changed # self.rightXVals[idStr] = map(int, val.tolist()) delete all lines in ramp canvas # assert name in ['Hue', 'Sat', 'Val', 'Opa' ] # print "drawHue" # this is for initializing and resets # nb val is the LENGTH of the line to draw # print "drawSaturation" # print "val i col", val, i, col # compute the value for q given line in canvas # compute the value for q given line in canvas # - self.canvasStart # *.6666666667 # use keyList = ['Sat', 'Val', 'Opa'] This object provides a OpenGL window that displays an RGBA color map # set to larger values to accelerate redraw # self.initTexture() guillaume: probably useless, the code is almost identical         in the overriden function OGLWidget.tkRedraw # guillaume: self.redraw() in OGLWidget.tkRedraw # print "redraw" # import pdb # test = ColorMapGUI() # def cb(ramp, min, max): # print len(ramp), min, max # test.addCallback(cb) ##cm = ColorMap('cmap', filename='/home/rhuey/python/dev/rgb.map') # cmg = ColorMapGUI(cm, allowRename=1) # for name, object in l.items(): #    if isinstance(object, ColorMap): #        cm = object #        break # test.mainloop()