Example #1
0
class RequestTablePanel(wx.Panel):
    def __init__(self, parent, window, controler):
        wx.Panel.__init__(self, parent, style=wx.TAB_TRAVERSAL)
        """ main sizer """
        requestPanelSizer = wx.FlexGridSizer(cols=2, hgap=0, rows=1, vgap=4)
        requestPanelSizer.AddGrowableCol(1)
        requestPanelSizer.AddGrowableRow(0)
        """ sizer with control buttons """
        controls_sizer = wx.BoxSizer(wx.VERTICAL)
        requestPanelSizer.AddSizer(controls_sizer, border=5, flag=wx.ALL)
        for name, bitmap, help in [
            ("AddVariableButton", "add_element", _("Add variable")),
            ("DeleteVariableButton", "remove_element", _("Remove variable")),
            ("UpVariableButton", "up", _("Move variable up")),
            ("DownVariableButton", "down", _("Move variable down"))
        ]:
            button = wx.lib.buttons.GenBitmapButton(self,
                                                    bitmap=GetBitmap(bitmap),
                                                    size=wx.Size(28, 28),
                                                    style=wx.NO_BORDER)
            button.SetToolTipString(help)
            setattr(self, name, button)
            controls_sizer.AddWindow(button, border=5, flag=wx.BOTTOM)
        """ variable grid """
        self.VariablesGrid = CustomGrid(self, style=wx.VSCROLL)
        self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE,
                                self.OnVariablesGridCellChange)
        self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK,
                                self.OnVariablesGridCellLeftClick)
        self.VariablesGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN,
                                self.OnVariablesGridEditorShown)
        requestPanelSizer.AddWindow(self.VariablesGrid, flag=wx.GROW)
        """ add header to grid """
        mainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=4)
        mainSizer.AddGrowableRow(1)
        mainSizer.AddGrowableCol(0)

        headerSizer = wx.BoxSizer(wx.HORIZONTAL)

        self.ipAddressDefault = {
            "Name": "ipAddres",
            "Address": "10.10.10.10",
            "Device ID": "",
            "Data type": "",
            "Transfer method": "",
            "Len": "1",
            "Modbus type": "",
            "Device ID": "1",
            "Period (ms)": "100",
            "Description": DESCRIPTION_IP,
        }
        self.portDefault = {
            "Name": "port",
            "Address": "502",
            "Device ID": "",
            "Data type": "",
            "Transfer method": "",
            "Len": "1",
            "Modbus type": "",
            "Device ID": "1",
            "Period (ms)": "100",
            "Description": DESCRIPTION_PORT
        }

        # виджеты для текста IP (label)
        labelIP = wx.StaticText(self, label="       Ip address: ")
        font = wx.Font(13, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL,
                       wx.FONTWEIGHT_BOLD)
        labelIP.SetFont(font)
        headerSizer.Add(labelIP)
        """ поле для IP """
        self.ip_address = IpAddrCtrl(self, size=(120, 22))
        wx.EVT_TEXT(self, self.ip_address.GetId(), self.OnChangeIp)
        """ wx.EVT_COMBOBOX(self, self.masterSelectCmbx.cmbbox.GetId(), self.OnChangeMasterOption) """
        headerSizer.Add(self.ip_address, flag=wx.ALIGN_CENTER_VERTICAL)
        """ виджеты для текста порта (label) """
        labelPort = wx.StaticText(self, label="      Port: ")
        font = wx.Font(13, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL,
                       wx.FONTWEIGHT_BOLD)
        labelPort.SetFont(font)
        headerSizer.Add(labelPort)
        """ поле для порта """
        self.port = IntCtrl(self,
                            min=0,
                            max=65535,
                            limited=True,
                            size=(70, 21))
        wx.EVT_TEXT(self, self.port.GetId(), self.OnChangePort)
        wx.EVT_TEXT(self, self.port.GetId(), self.OnChangePort)

        headerSizer.Add(self.port, flag=wx.ALIGN_CENTER_VERTICAL)

        mainSizer.AddSizer(headerSizer, flag=wx.GROW)
        mainSizer.AddSizer(requestPanelSizer, flag=wx.GROW)
        self.SetSizer(mainSizer)
        self.ParentWindow = window
        self.Controler = controler

        self.VariablesDefaultValue = {
            "Name": "",
            "Address": "1",
            "Len": "1",
            "Data type": "WORD",
            "Modbus type": HOLDING_REGISTER_READ,
            "Description": DESCRIPTION,
            "Device ID": "1",
            "Transfer method": "Periodic",
            "Period (ms)": "100"
        }
        self.Table = MBRequestDataTable(self)
        self.ColAlignements = [wx.ALIGN_RIGHT] + \
                              [wx.ALIGN_LEFT]*(len(self.VariablesDefaultValue))
        self.ColSizes = [20, 150
                         ] + [100] * (len(self.VariablesDefaultValue) - 1)
        self.VariablesGrid.SetTable(self.Table)
        self.VariablesGrid.SetButtons({
            "Add": self.AddVariableButton,
            "Delete": self.DeleteVariableButton,
            "Up": self.UpVariableButton,
            "Down": self.DownVariableButton
        })
        """ handlers for adding variable """
        def _AddVariable(new_row):
            if new_row > 0:
                row_content = self.Table.data[new_row - 1].copy()
                newAddr = int(row_content["Address"])
                newLen = int(row_content["Len"])
                if row_content["Data type"] in ("REAL", "INT"):
                    newLen = newLen * 2
                newAddr = newAddr + newLen
                row_content["Address"] = str(newAddr)
                result = VARIABLE_NAME_SUFFIX_MODEL.search(row_content["Name"])
                if result is not None:
                    name = row_content["Name"][:result.start(1)]
                    suffix = result.group(1)
                    if suffix != "":
                        start_idx = int(suffix)
                    else:
                        start_idx = 0
                else:
                    name = row_content["Name"]
                    start_idx = 0
                row_content["Name"] = self.Controler.GenerateNewName(
                    name + "%d", start_idx)
            else:
                row_content = self.VariablesDefaultValue.copy()
            self.Table.InsertRow(new_row, row_content)
            self.RefreshModel()
            self.RefreshView()
            return new_row

        setattr(self.VariablesGrid, "_AddRow", _AddVariable)
        """ handlers for deleting variable """

        def _DeleteVariable(row):
            self.Table.RemoveRow(row)
            self.RefreshModel()
            self.RefreshView()

        setattr(self.VariablesGrid, "_DeleteRow", _DeleteVariable)
        """ handlers for moving varible """

        def _MoveVariable(row, move):
            new_row = self.Table.MoveRow(row, move)
            if new_row != row:
                self.RefreshModel()
                self.RefreshView()
            return new_row

        setattr(self.VariablesGrid, "_MoveRow", _MoveVariable)

        self.VariablesGrid.SetRowLabelSize(0)
        for col in range(self.Table.GetNumberCols()):
            attr = wx.grid.GridCellAttr()
            attr.SetAlignment(self.ColAlignements[col], wx.ALIGN_CENTRE)
            self.VariablesGrid.SetColAttr(col, attr)
            self.VariablesGrid.SetColSize(col, self.ColSizes[col])
        self.Table.ResetView(self.VariablesGrid)

        self.Bind(wx.EVT_SHOW, self.OnShow)

    def OnChangeMasterOption(self, event):
        masterOptionOnFrame = self.masterSelectCmbx.cmbbox.GetStringSelection()
        masterOptionInXml = [
            i for i in self.Controler.GetVariables()
            if i["Name"] == MASTER_OPTION
        ]
        if len(masterOptionInXml) > 0:
            if masterOptionOnFrame != masterOptionInXml[0]:
                self.RefreshModel()
        else:
            self.RefreshModel()
        event.Skip()

    def GetMasterOption(self):
        return {
            "Name": "Master option",
            "Address": "",
            "Len": "",
            "Device ID": "",
            "Data type": u"WORD",
            "Transfer method": "",
            "Period (ms)": "",
            "Description": MASTER_OPTION,
            "Modbus type": "0"
        }

    def RefreshModel(self):
        ipAddress = self.ipAddressDefault.copy()
        ipAddress["Address"] = self.ip_address.GetValue()
        controllerVariables = self.Controler.GetVariables()
        controllerVariables = [
            i for i in controllerVariables
            if i["Description"] not in (DESCRIPTION, MASTER_OPTION)
        ]
        controllerVariables += self.Table.GetData()
        controllerVariables.append(self.GetMasterOption())
        controllerVariables.append(ipAddress)
        controllerVariables.append(self.portDefault)
        self.Controler.SetVariables(controllerVariables)
        self.RefreshBuffer()

    def RefreshView(self):
        varForTable = self.Controler.GetVariables()

        varForTable = [
            i for i in varForTable if i["Description"] == DESCRIPTION
        ]
        self.Table.SetData(varForTable)
        self.Table.ResetView(self.VariablesGrid)
        varForTable = self.Controler.GetVariables()
        varForTable = [i for i in varForTable if i["Name"] == MASTER_OPTION]
        #if len(varForTable) > 0:
        #self.masterSelectCmbx.cmbbox.SetStringSelection(varForTable[0]["Modbus type"])
        self.VariablesGrid.RefreshButtons()

        varForTable = self.Controler.GetVariables()
        varForTable = [
            i for i in varForTable if i["Description"] == DESCRIPTION_IP
        ]
        if len(varForTable) == 0:
            varForTable = []
            varForTable.append(self.ipAddressDefault)
        self.ip_address.SetValue(varForTable[0]["Address"])

        varForTable = self.Controler.GetVariables()
        vars = [i for i in varForTable if i["Description"] == DESCRIPTION_PORT]
        if len(vars) == 0:
            vars = []
            vars.append(self.portDefault)
        # if self.port.GetLineText != vars[0]["Address"]:
        #     print vars
        self.port.SetValue(int(vars[0]["Address"]))

    def OnShow(self, event):
        pass
        # print 'kek'

    # используется для событий, когда изменяются поля ip-адреса и порта
    def OnChangeIp(self, event):
        ipAddress = self.ipAddressDefault.copy()
        ipAddress["Address"] = self.ip_address.GetValue().replace(' ', '')
        # port = self.portDefault.copy()
        # port["Address"] = self.port.GetLineText(0)
        controllerVariables = self.Controler.GetVariables()
        # valuesOnFrame = self.GetData()
        valueIPOnWidget = self.ip_address.GetValue()
        controllerVariablesIP = [
            i for i in controllerVariables
            if i["Description"] == (DESCRIPTION_IP)
        ]
        # valuePortOnWidget = self.port.GetLineText()
        controllerVariablesIP = [
            i for i in controllerVariables
            if i["Description"] == (DESCRIPTION_PORT)
        ]
        if not (ipAddress in controllerVariables):
            controllerVariables = [
                i for i in controllerVariables
                if i["Description"] != DESCRIPTION_IP
            ]
            controllerVariables.append(ipAddress)
            # controllerVariables.append(port)
            self.Controler.SetVariables(controllerVariables)
            self.RefreshBuffer()

        event.Skip()

    def OnChangePort(self, event):
        portAddress = self.portDefault.copy()
        portAddress["Address"] = self.port.GetLineText(0)
        controllerVariables = self.Controler.GetVariables()
        if not (portAddress in controllerVariables):
            controllerVariables = [
                i for i in controllerVariables
                if i["Description"] != DESCRIPTION_PORT
            ]
            controllerVariables.append(portAddress)
            self.Controler.SetVariables(controllerVariables)
            self.RefreshBuffer()
        event.Skip()

    # def GetData(self):
    #     """
    #     Считывает с GUI настроенные пользователем параметры и возвращает их в виде списка
    #     словарей
    #     """

    def OnVariablesGridCellChange(self, event):
        row, col = event.GetRow(), event.GetCol()
        colname = self.Table.GetColLabelValue(col, False)
        value = self.Table.GetValue(row, col)
        message = None

        if colname == "Modbus type":
            self.VariablesGrid.SetCellValue(row, col + 1, "WORD")

        if colname == "Len":
            modbusType = self.Table.GetValue(row, 4)  # Modubs type value
            if modbusType in (HOLDING_REGISTER_READ, INPUT_REGISTER_READ):
                if int(value) > MAX_SIMULTANEOUS_REGISTERS_READ:
                    value = MAX_SIMULTANEOUS_REGISTERS_READ
                    self.VariablesGrid.SetCellValue(
                        row, col, str(MAX_SIMULTANEOUS_REGISTERS_READ))
            if modbusType == HOLDING_REGISTER_WRITE:
                if int(value) > MAX_SIMULTANEOUS_REGISTERS_WRITE:
                    self.VariablesGrid.SetCellValue(
                        row, col, str(MAX_SIMULTANEOUS_REGISTERS_WRITE))
            if modbusType in (COIL_READ, DISCRETE_INPUT_READ):
                if int(value) > MAX_SIMULTANEOUS_COIL_DISC_READ:
                    self.VariablesGrid.SetCellValue(
                        row, col, str(MAX_SIMULTANEOUS_COIL_DISC_READ))
            if modbusType == COIL_WRITE:
                if int(value) > MAX_SIMULTANEOUS_COIL_WRITE:
                    self.VariablesGrid.SetCellValue(
                        row, col, str(MAX_SIMULTANEOUS_COIL_WRITE))

        if colname == "Name" and value != "":
            if not TestIdentifier(value):
                message = _("\"%s\" is not a valid identifier!") % value
            elif value.upper() in IEC_KEYWORDS:
                message = _("\"%s\" is a keyword. It can't be used!") % value
            elif value.upper() in [
                    var["Name"].upper()
                    for var_row, var in enumerate(self.Table.data)
                    if var_row != row
            ]:
                message = _(
                    "A variable with \"%s\" as name already exists!") % value
            else:
                self.RefreshModel()
                wx.CallAfter(self.RefreshView)
        else:
            self.RefreshModel()
            wx.CallAfter(self.RefreshView)

        if message is not None:
            dialog = wx.MessageDialog(self, message, _("Error"),
                                      wx.OK | wx.ICON_ERROR)
            dialog.ShowModal()
            dialog.Destroy()
            event.Veto()
        else:
            event.Skip()

    def DoGetBestSize(self):
        return self.ParentWindow.GetPanelBestSize()

    def OnVariablesGridEditorShown(self, event):
        event.Skip()

    def GetVariableTypeFunction(self, base_type):
        def VariableTypeFunction(event):
            row = self.VariablesGrid.GetGridCursorRow()
            self.Table.SetValueByName(row, "Data type", base_type)
            self.Table.ResetView(self.VariablesGrid)
            self.RefreshModel()
            self.RefreshView()
            event.Skip()

        return VariableTypeFunction

    def OnVariablesGridCellLeftClick(self, event):
        if event.GetCol() == 0:
            row = event.GetRow()
            data_type = self.Table.GetValueByName(row, "Data type")
            var_name = self.Table.GetValueByName(row, "Name")
            data = wx.TextDataObject(
                str((var_name, "Global", data_type,
                     self.Controler.GetCurrentLocation())))
            dragSource = wx.DropSource(self.VariablesGrid)
            dragSource.SetData(data)
            dragSource.DoDragDrop()
            return
        event.Skip()

    def RefreshBuffer(self):
        self.Controler.BufferCodeFile()
        self.ParentWindow.RefreshTitle()
        self.ParentWindow.RefreshFileMenu()
        self.ParentWindow.RefreshEditMenu()
        self.ParentWindow.RefreshPageTitles()
Example #2
0
class OptionPanel(wx.Panel):
	"""
	A panel with all the available options to customize the plot.
	Some are mandatory, others are just optional.
	"""
	def __init__(self, parent, size : tuple, dataset : nc.Dataset, metadata : dict):
		super(OptionPanel, self).__init__(parent=parent, id=wx.ID_ANY, size=size)
		self.parent = parent
		self.dataset = dataset
		self.metadata = metadata
		self.options = {} # It will gather all the options set by the user
		self.init_options() # Initialize the options dictionary
		
		self.var_ids = {} # Dictionary with id keys and their corresponing variable
		self.c_boxes = [] # List of ComboBox used
		self.text_entries = [] # List of text entries used
		self.chk_boxes = [] # List of check boxes used

		self.main_sizer = wx.BoxSizer(wx.VERTICAL)

		# --------------------------------------- #
		# First StaticBox, general options:
		# Variable / Time index / Level (if necessary)
		stbox_gen = wx.StaticBox(parent=self, label="General")
		stbox_gen_sizer = wx.StaticBoxSizer(stbox_gen, wx.HORIZONTAL)
		
		# Variables
		text_variables = wx.StaticText(parent=stbox_gen, label="Variable : ")
		l_variables = nc_tools.get_variables(self.dataset)
		self.c_box_variables = wx.ComboBox(
									  parent=stbox_gen,
									  id=wx.ID_ANY,
									  choices=l_variables,
									  style=wx.CB_DROPDOWN | wx.CB_READONLY
									  )
		self.var_ids[self.c_box_variables.GetId()] = "variable"
		self.c_boxes.append(self.c_box_variables)

		# Time
		text_time = wx.StaticText(parent=stbox_gen, label="Time index : ")
		timesteps =  nc_tools.get_timesteps(self.dataset)
		self.c_box_time = wx.ComboBox(
									  parent=stbox_gen,
									  id=wx.ID_ANY,
									  choices=timesteps,
									  style=wx.CB_DROPDOWN | wx.CB_READONLY
									  )
		self.var_ids[self.c_box_time.GetId()] = "time_index"
		self.c_boxes.append(self.c_box_time)

		# Pressure Level (if necessary) 
		if nc_tools.is_pressure_level(meta=self.metadata):
			text_levels = wx.StaticText(parent=stbox_gen, label="Pressure level : ")
			levels = nc_tools.get_pressure_levels(self.dataset)
			self.c_box_levels = wx.ComboBox(
									  		parent=stbox_gen,
									  		id=wx.ID_ANY,
									 	 	choices=levels,
									  		style=wx.CB_DROPDOWN | wx.CB_READONLY
									  		)
			self.var_ids[self.c_box_levels.GetId()] = "pl_index"
			self.c_boxes.append(self.c_box_levels)
		else:
			self.c_box_levels = None

		# StaticBox sizer setup
		stbox_gen_sizer.Add(text_variables, 0, wx.ALIGN_CENTER | wx.LEFT | wx.TOP | wx.BOTTOM, 20)
		stbox_gen_sizer.Add(self.c_box_variables, 0, wx.ALIGN_CENTER | wx.ALL, 20)
		stbox_gen_sizer.Add(text_time, 0, wx.ALIGN_CENTER | wx.LEFT | wx.TOP | wx.BOTTOM, 20)
		stbox_gen_sizer.Add(self.c_box_time, 0, wx.ALIGN_CENTER | wx.ALL, 20)
		if self.c_box_levels:
			# Add levels to the sizer if dataset contains levels
			stbox_gen_sizer.Add(text_levels, 0, wx.ALIGN_CENTER | wx.LEFT | wx.TOP | wx.BOTTOM, 20)
			stbox_gen_sizer.Add(self.c_box_levels, 0, wx.ALIGN_CENTER | wx.ALL, 20)

		# --------------------------------------- #
		# Second StaticBox, data corrections
		stbox_data_corr = wx.StaticBox(parent=self, label="Corrections")
		stbox_data_corr_sizer = wx.StaticBoxSizer(stbox_data_corr, wx.VERTICAL)
		pnl_data_corr = wx.Panel(parent=stbox_data_corr)
		pnl_data_corr_sizer = wx.GridSizer(cols=6, gap=(5, 5))

		# Longitude offset
		text_lon_offset = wx.StaticText(parent=pnl_data_corr, label="Longitude offset : ")
		self.te_lon_offset = NumCtrl(parent=pnl_data_corr, id=wx.ID_ANY, value=0, integerWidth=3, fractionWidth=2)
		self.var_ids[self.te_lon_offset.GetId()] = "lon_offset"
		self.text_entries.append(self.te_lon_offset)

		# Data multiplicator
		text_coef = wx.StaticText(parent=pnl_data_corr, label="Apply coefficient : ")
		self.te_coef = NumCtrl(parent=pnl_data_corr, id=wx.ID_ANY, value=1, integerWidth=3, fractionWidth=2)
		self.var_ids[self.te_coef.GetId()] = "coef"
		self.text_entries.append(self.te_coef)

		# Data offset
		text_data_offset = wx.StaticText(parent=pnl_data_corr, label="Data offset : ")
		self.te_data_offset = NumCtrl(parent=pnl_data_corr, id=wx.ID_ANY, value=0, integerWidth=3, fractionWidth=2)
		self.var_ids[self.te_data_offset.GetId()] = "offset"
		self.text_entries.append(self.te_data_offset)

		# StaticBox sizer setup
		pnl_data_corr_sizer.Add(text_lon_offset, 0, wx.EXPAND | wx.LEFT | wx.TOP | wx.BOTTOM, 20)
		pnl_data_corr_sizer.Add(self.te_lon_offset, 0, wx.EXPAND | wx.ALL, 20)
		pnl_data_corr_sizer.Add(text_coef, 0, wx.EXPAND | wx.LEFT | wx.TOP | wx.BOTTOM, 20)
		pnl_data_corr_sizer.Add(self.te_coef, 0, wx.EXPAND | wx.ALL, 20)
		pnl_data_corr_sizer.Add(text_data_offset, 0, wx.EXPAND | wx.LEFT | wx.TOP | wx.BOTTOM, 20)
		pnl_data_corr_sizer.Add(self.te_data_offset, 0, wx.EXPAND | wx.ALL, 20)
		pnl_data_corr.SetSizer(pnl_data_corr_sizer)

		stbox_data_corr_sizer.Add(pnl_data_corr, 0, wx.EXPAND)

		# --------------------------------------- #
		# Third StaticBox, projection setup
		stbox_proj = wx.StaticBox(parent=self, label="Map setup")
		stbox_proj_sizer = wx.StaticBoxSizer(stbox_proj, wx.VERTICAL)

		pnl_stbox_proj = wx.Panel(parent=stbox_proj)
		pnl_stbox_proj_sizer = wx.GridBagSizer(0, 0)

		# Panel projection #
		pnl_proj = wx.Panel(parent=pnl_stbox_proj)
		pnl_proj_sizer = wx.GridSizer(cols=2, gap=(5, 5))
		
		text_preset = wx.StaticText(parent=pnl_proj, label="Map preset : ")
		with open(MAP_PRESETS_PATH, 'r') as foo:
			self.presets = json.load(foo)
			foo.close()
		presets_list = list(self.presets.keys())
		self.c_box_presets = wx.ComboBox(
									  parent=pnl_proj,
									  id=wx.ID_ANY,
									  choices=presets_list,
									  style=wx.CB_DROPDOWN | wx.CB_READONLY
									  )
		self.var_ids[self.c_box_presets.GetId()] = "preset"
		self.c_boxes.append(self.c_box_presets)

		# Sizer setup
		pnl_proj_sizer.Add(text_preset, 0, wx.ALIGN_CENTER_HORIZONTAL, 20)
		pnl_proj_sizer.Add(self.c_box_presets, 0, wx.ALIGN_CENTER_HORIZONTAL, 20)
		pnl_proj.SetSizer(pnl_proj_sizer)

		# Panel other options #
		pnl_other = wx.Panel(parent=pnl_stbox_proj)
		pnl_other_sizer = wx.GridSizer(cols=2, gap=(5, 5))

		text_res = wx.StaticText(parent=pnl_other, label="Resolution : ")
		l_resolutions = ['c', 'l', 'i', 'h', 'f']
		self.c_box_res = wx.ComboBox(
									 parent=pnl_other,
									 id=wx.ID_ANY,
									 choices=l_resolutions,
									 style=wx.CB_DROPDOWN | wx.CB_READONLY,
									 size=(100, 25)
									 )
		self.var_ids[self.c_box_res.GetId()] = "resolution"
		self.c_boxes.append(self.c_box_res)

		self.check_countries = wx.CheckBox(parent=pnl_other, id=wx.ID_ANY, label=" Draw countries")
		self.var_ids[self.check_countries.GetId()] = "countries"
		self.chk_boxes.append(self.check_countries)

		self.check_rivers = wx.CheckBox(parent=pnl_other, id=wx.ID_ANY, label=" Draw rivers")
		self.var_ids[self.check_rivers.GetId()] = "rivers"
		self.chk_boxes.append(self.check_rivers)

		text_cmap = wx.StaticText(parent=pnl_other, label="Colormap : ")
		colormaps = display_tools.get_cmap()
		self.c_box_cmap = wx.ComboBox(
									  parent=pnl_other,
									  id=wx.ID_ANY,
									  choices=colormaps,
									  style=wx.CB_DROPDOWN | wx.CB_READONLY,
									  size=(100, 25)
									  )
		self.var_ids[self.c_box_cmap.GetId()] = "cmap"
		self.c_boxes.append(self.c_box_cmap)

		text_pltype = wx.StaticText(parent=pnl_other, label="Plot type : ")
		plot_types = ["pcolormesh"]
		self.c_box_pltype = wx.ComboBox(
									  parent=pnl_other,
									  id=wx.ID_ANY,
									  choices=plot_types,
									  style=wx.CB_DROPDOWN | wx.CB_READONLY,
									  size=(100, 25)
									  )
		self.var_ids[self.c_box_pltype.GetId()] = "plot_type"
		self.c_boxes.append(self.c_box_pltype)

		self.check_colorbar = wx.CheckBox(parent=pnl_other, id=wx.ID_ANY, label=" Colorbar")
		self.var_ids[self.check_colorbar.GetId()] = "colorbar"
		self.chk_boxes.append(self.check_colorbar)

		self.check_norm = wx.CheckBox(parent=pnl_other, id=wx.ID_ANY, label=" Norm")
		self.var_ids[self.check_norm.GetId()] = "norm"
		# This check box is not added to the list of check boxes because it'll have its own binding.

		text_midpoint = wx.StaticText(parent=pnl_other, label="Midpoint : ")
		self.te_midpoint = IntCtrl(parent=pnl_other, id=wx.ID_ANY, value=25)
		self.var_ids[self.te_midpoint.GetId()] = "midpoint"
		self.text_entries.append(self.te_midpoint)
		self.te_midpoint.Enable(False)

		text_min = wx.StaticText(parent=pnl_other, label="Min : ")
		self.te_min = IntCtrl(parent=pnl_other, id=wx.ID_ANY, value=0)
		self.var_ids[self.te_min.GetId()] = "c_min"
		self.text_entries.append(self.te_min)
		self.te_min.Enable(False)

		text_max = wx.StaticText(parent=pnl_other, label="Max : ")
		self.te_max = IntCtrl(parent=pnl_other, id=wx.ID_ANY, value=50)
		self.var_ids[self.te_max.GetId()] = "c_max"
		self.text_entries.append(self.te_max)
		self.te_max.Enable(False)

		# Sizer setup
		pnl_other_sizer.Add(text_res, 0)
		pnl_other_sizer.Add(self.c_box_res, 0)
		pnl_other_sizer.Add(self.check_countries, 0)
		pnl_other_sizer.Add(self.check_rivers, 0)
		pnl_other_sizer.Add(text_cmap, 0)
		pnl_other_sizer.Add(self.c_box_cmap, 0)
		pnl_other_sizer.Add(text_pltype, 0)
		pnl_other_sizer.Add(self.c_box_pltype, 0)
		pnl_other_sizer.Add(self.check_colorbar, 0)
		pnl_other_sizer.Add(self.check_norm, 0)
		pnl_other_sizer.Add(text_midpoint, 0)
		pnl_other_sizer.Add(self.te_midpoint, 0)
		pnl_other_sizer.Add(text_min, 0)
		pnl_other_sizer.Add(self.te_min, 0)
		pnl_other_sizer.Add(text_max, 0)
		pnl_other_sizer.Add(self.te_max, 0)
		pnl_other.SetSizer(pnl_other_sizer)

		# Map preview panels
		pnl_map_preview = wx.Panel(parent=pnl_stbox_proj, style=wx.BORDER_THEME)
		pnl_map_preview.SetBackgroundColour(wx.Colour(255, 255, 255))
		pnl_map_preview_sizer = wx.BoxSizer(wx.VERTICAL)

		self.map_previews = {}
		for preset in self.presets.keys():
			filename = os.path.join(MAP_PREVIEW_PATH, self.presets[preset]['filename'])
			image = wx.Image(filename, wx.BITMAP_TYPE_ANY)
			bitmap = wx_tools.rescale_image(image, 400, 300)
			self.map_previews[preset] = wx.StaticBitmap(pnl_map_preview, wx.ID_ANY, bitmap, size=(400,300))
			pnl_map_preview_sizer.Add(self.map_previews[preset], 0, wx.EXPAND)
			self.map_previews[preset].Hide()

		self.map_previews[self.options['preset']].Show()

		pnl_map_preview.SetSizer(pnl_map_preview_sizer)

		# StaticBox Sizer setup
		pnl_stbox_proj_sizer.Add(pnl_proj, pos=(0, 0), span=(1, 1), flag=wx.EXPAND | wx.ALL, border=20)
		pnl_stbox_proj_sizer.Add(pnl_other, pos=(0, 1), span=(1, 1), flag=wx.EXPAND | wx.ALL, border=20)
		pnl_stbox_proj_sizer.Add(pnl_map_preview, pos=(0, 2), span=(1, 2), flag=wx.EXPAND | wx.ALL, border=20)
		pnl_stbox_proj.SetSizer(pnl_stbox_proj_sizer)

		stbox_proj_sizer.Add(pnl_stbox_proj, 0, wx.ALIGN_CENTER)

		# --------------------------------------- #
		# PLot Button

		self.button = wx.Button(parent=self, label="Draw", size=(200, 30))

		# --------------------------------------- #
		# Bindings
		for c_box in self.c_boxes:
			c_box.Bind(wx.EVT_COMBOBOX, handler=self.on_option_change)
		for te in self.text_entries:
			te.Bind(wx.EVT_TEXT, handler=self.on_option_change)
		for chk in self.chk_boxes:
			chk.Bind(wx.EVT_CHECKBOX, handler=self.on_option_change)
		self.check_norm.Bind(wx.EVT_CHECKBOX, handler=self.on_norm_change)

		# --------------------------------------- #
		# Add element to the main sizer
		self.main_sizer.Add(stbox_gen_sizer, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 20)
		self.main_sizer.Add(stbox_data_corr_sizer, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 20)
		self.main_sizer.Add(stbox_proj_sizer, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 20)
		self.main_sizer.Add(self.button, 0, wx.ALIGN_CENTER | wx.ALL, 20)
		self.SetSizer(self.main_sizer)

	def on_option_change(self, event):
		"""
		Event handler catching all the option changes.
		"""
		element = event.GetEventObject()
		_id = element.GetId()
		var_name = self.var_ids[_id]
		if var_name == 'time_index' or var_name == 'pl_index':
			val = int(element.GetValue().split(" ")[0])
		elif var_name == 'preset':
			val = element.GetValue()
			self.display_map_preview(val)
		else:
			val = element.GetValue()
		self.update_option(var_name, val)
		event.Skip()

	def on_norm_change(self, event):
		"""
		Enable or disable text entries for colorbar setup.
		"""
		chk_box = event.GetEventObject()
		val = chk_box.GetValue()
		self.options[self.var_ids[chk_box.GetId()]] = val
		self.te_midpoint.Enable(val)
		self.te_min.Enable(val)
		self.te_max.Enable(val)
		event.Skip()

	def init_options(self):
		"""
		Initialize the map options.
		"""
		self.options = {
			"variable": nc_tools.get_variables(self.dataset)[0],
			"time_index": None,
			"pl_index": None,
			"lon_offset": 0,
			"coef": 1,
			"offset": 0,
			"preset": "default",
			"resolution": 'i',
			"countries": False,
			"rivers": False,
			"cmap": "seismic",
			"colorbar": False,
			"norm": False,
			"c_min": 0,
			"c_max": 50,
			"midpoint": 25,
			"plot_type": "pcolormesh"
		}

	def update_option(self, var_name : str, val):
		"""
		Update the options: assign value :val: to the option associated with element with respect to the associated variable.
		"""
		try:
			self.options[var_name] = val
		except Exception as e:
			raise e

	def display_map_preview(self, preset):
		"""
		Display the map preview associated with the chosen preset.
		"""
		self.map_previews[self.options['preset']].Hide()
		self.map_previews[preset].Show()