source: sasview/src/sas/sasgui/perspectives/file_converter/converter_panel.py @ 05595c4

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since 05595c4 was 05595c4, checked in by lewis, 8 years ago

Finish implementing 2D BSL loader

  • Property mode set to 100644
File size: 20.4 KB
RevLine 
[77d92cd]1"""
2This module provides a GUI for the file converter
3"""
4
5import wx
6import sys
[05595c4]7import os
[a58706d]8import numpy as np
[77d92cd]9from wx.lib.scrolledpanel import ScrolledPanel
10from sas.sasgui.guiframe.panel_base import PanelBase
11from sas.sasgui.perspectives.calculator import calculator_widgets as widget
[c9a519f]12from sas.sasgui.perspectives.file_converter.converter_widgets import VectorInput
[de0df2c]13from sas.sasgui.perspectives.file_converter.meta_panels import MetadataWindow
14from sas.sasgui.perspectives.file_converter.meta_panels import DetectorPanel
[2a7722b]15from sas.sasgui.perspectives.file_converter.meta_panels import SamplePanel
[55bc56bc]16from sas.sasgui.perspectives.file_converter.meta_panels import SourcePanel
[eb8da5f]17from sas.sasgui.perspectives.file_converter.frame_select_dialog import FrameSelectDialog
[a58706d]18from sas.sasgui.guiframe.events import StatusEvent
[11794f2]19from sas.sasgui.guiframe.documentation_window import DocumentationWindow
[a58706d]20from sas.sasgui.guiframe.dataFitting import Data1D
[535e181]21from sas.sascalc.dataloader.data_info import Data2D
[fdbea3c]22from sas.sasgui.guiframe.utils import check_float
[8976865]23from sas.sasgui.perspectives.file_converter.cansas_writer import CansasWriter
[05595c4]24from sas.sascalc.dataloader.readers.red2d_reader import Reader as Red2DWriter
[535e181]25from sas.sasgui.perspectives.file_converter.bsl_loader import BSLLoader as OTOKOLoader
26from sas.sascalc.file_converter.bsl_loader import BSLLoader
[f2b3f28]27from sas.sascalc.dataloader.data_info import Detector
[2a7722b]28from sas.sascalc.dataloader.data_info import Sample
[55bc56bc]29from sas.sascalc.dataloader.data_info import Source
[fdbea3c]30from sas.sascalc.dataloader.data_info import Vector
[77d92cd]31
32# Panel size
33if sys.platform.count("win32") > 0:
34    PANEL_TOP = 0
35    _STATICBOX_WIDTH = 410
36    _BOX_WIDTH = 200
[36f4debb]37    PANEL_SIZE = 480
[77d92cd]38    FONT_VARIANT = 0
39else:
40    PANEL_TOP = 60
41    _STATICBOX_WIDTH = 430
42    _BOX_WIDTH = 200
[36f4debb]43    PANEL_SIZE = 500
[77d92cd]44    FONT_VARIANT = 1
45
46class ConverterPanel(ScrolledPanel, PanelBase):
47
48    def __init__(self, parent, base=None, *args, **kwargs):
49        ScrolledPanel.__init__(self, parent, *args, **kwargs)
50        PanelBase.__init__(self)
[a58706d]51        self.SetupScrolling()
[77d92cd]52        self.SetWindowVariant(variant=FONT_VARIANT)
53
54        self.base = base
55        self.parent = parent
[de0df2c]56        self.meta_frames = []
[77d92cd]57
[a58706d]58        self.q_input = None
59        self.iq_input = None
60        self.output = None
[4b862c4]61        self.data_type = "ascii"
[a58706d]62
[503cc34]63        self.title = None
64        self.run = None
65        self.run_name = None
66        self.instrument = None
67        self.detector = Detector()
68        self.sample = Sample()
69        self.source = Source()
70        self.properties = ['title', 'run', 'run_name', 'instrument']
71
72        self.detector.name = ''
73        self.source.radiation = 'neutron'
[4b862c4]74
[a58706d]75        self._do_layout()
[77d92cd]76        self.SetAutoLayout(True)
77        self.Layout()
78
[94f4518]79    def convert_to_cansas(self, frame_data, filename, single_file):
[8976865]80        reader = CansasWriter()
[ea2a7348]81        entry_attrs = None
82        if self.run_name is not None:
83            entry_attrs = { 'name': self.run_name }
[94f4518]84        if single_file:
85            reader.write(filename, frame_data,
86                sasentry_attrs=entry_attrs)
87        else:
88            # strip extension from filename
89            ext = "." + filename.split('.')[-1]
90            name = filename.replace(ext, '')
91            for i in range(len(frame_data)):
92                f_name = "{}{}{}".format(name, i+1, ext)
93                reader.write(f_name, [frame_data[i]],
94                    sasentry_attrs=entry_attrs)
[a58706d]95
[535e181]96    def extract_ascii_data(self, filename):
[a58706d]97        data = np.loadtxt(filename, dtype=str)
98
[ff790b3]99        if len(data.shape) != 1:
100            msg = "Error reading {}: Only one column of data is allowed"
101            raise Exception(msg.format(filename.split('\\')[-1]))
102
[a58706d]103        is_float = True
104        try:
105            float(data[0])
106        except:
107            is_float = False
108
109        if not is_float:
110            end_char = data[0][-1]
111            # If lines end with comma or semi-colon, trim the last character
112            if end_char == ',' or end_char == ';':
113                data = map(lambda s: s[0:-1], data)
114            else:
115                msg = ("Error reading {}: Lines must end with a digit, comma "
116                    "or semi-colon").format(filename.split('\\')[-1])
117                raise Exception(msg)
118
119        return np.array(data, dtype=np.float32)
120
[535e181]121    def extract_otoko_data(self, filename):
122        loader = OTOKOLoader(self.q_input.GetPath(),
123            self.iq_input.GetPath())
124        bsl_data = loader.load_bsl_data()
125        qdata = bsl_data.q_axis.data
126        iqdata = bsl_data.data_axis.data
127        if len(qdata) > 1:
128            msg = ("Q-Axis file has multiple frames. Only 1 frame is "
129                "allowed for the Q-Axis")
130            wx.PostEvent(self.parent.manager.parent,
131                StatusEvent(status=msg, info="error"))
132            return
133        else:
134            qdata = qdata[0]
135
136        return qdata, iqdata
137
[eb8da5f]138    def ask_frame_range(self, n_frames):
139        valid_input = False
[05595c4]140        is_bsl = (self.data_type == 'bsl')
141        dlg = FrameSelectDialog(n_frames, is_bsl)
[eb8da5f]142        frames = None
143        increment = None
[94f4518]144        single_file = True
[eb8da5f]145        while not valid_input:
146            if dlg.ShowModal() == wx.ID_OK:
147                msg = ""
148                try:
149                    first_frame = int(dlg.first_input.GetValue())
150                    last_frame = int(dlg.last_input.GetValue())
151                    increment = int(dlg.increment_input.GetValue())
[05595c4]152                    if not is_bsl:
153                        single_file = dlg.single_btn.GetValue()
154
[eb8da5f]155                    if last_frame < 0 or first_frame < 0:
156                        msg = "Frame values must be positive"
157                    elif increment < 1:
158                        msg = "Increment must be greater than or equal to 1"
159                    elif first_frame > last_frame:
160                        msg = "First frame must be less than last frame"
[05595c4]161                    elif last_frame >= n_frames:
[eb8da5f]162                        msg = "Last frame must be less than {}".format(n_frames)
163                    else:
164                        valid_input = True
165                except:
166                    valid_input = False
167                    msg = "Please enter valid integer values"
168
169                if not valid_input:
170                    wx.PostEvent(self.parent.manager.parent,
171                        StatusEvent(status=msg))
172            else:
[94f4518]173                return { 'frames': [], 'inc': None, 'file': single_file }
[eb8da5f]174        frames = range(first_frame, last_frame + increment,
175            increment)
[94f4518]176        return { 'frames': frames, 'inc': increment, 'file': single_file }
[eb8da5f]177
[a58706d]178    def on_convert(self, event):
[fdbea3c]179        if not self.validate_inputs():
180            return
181
[503cc34]182        self.sample.ID = self.title
[3ea9371]183
[a58706d]184        try:
[4b862c4]185            if self.data_type == 'ascii':
[535e181]186                qdata = self.extract_ascii_data(self.q_input.GetPath())
187                iqdata = np.array([self.extract_ascii_data(self.iq_input.GetPath())])
188            elif self.data_type == 'otoko':
189                qdata, iqdata = self.extract_otoko_data(self.q_input.GetPath())
[4b862c4]190            else: # self.data_type == 'bsl'
[535e181]191                loader = BSLLoader(self.iq_input.GetPath())
192                frames = [0]
193                if loader.n_frames > 1:
194                    params = self.ask_frame_range(loader.n_frames)
[94f4518]195                    frames = params['frames']
[05595c4]196                data = {}
197
[535e181]198                for frame in frames:
199                    loader.frame = frame
[05595c4]200                    data[frame] = loader.load_data()
201
202                # TODO: Tidy this up
203                # Prepare axes values (arbitrary scale)
[535e181]204                data_x = []
205                data_y = range(loader.n_pixels) * loader.n_rasters
206                for i in range(loader.n_rasters):
207                    data_x += [i] * loader.n_pixels
[05595c4]208
209                file_path = self.output.GetPath()
210                filename = os.path.split(file_path)[-1]
211                file_path = os.path.split(file_path)[0]
212                for i, frame in data.iteritems():
213                    # If more than 1 frame is being exported, append the frame
214                    # number to the filename
215                    if len(data) > 1:
216                        frame_filename = filename.split('.')
217                        frame_filename[0] += str(i+1)
218                        frame_filename = '.'.join(frame_filename)
219                    else:
220                        frame_filename = filename
221
222                    data_i = frame.reshape((loader.n_pixels*loader.n_rasters,1))
223                    data_info = Data2D(data=data_i, qx_data=data_x, qy_data=data_y)
224                    writer = Red2DWriter()
225                    writer.write(os.path.join(file_path, frame_filename), data_info)
226
[535e181]227                wx.PostEvent(self.parent.manager.parent,
228                    StatusEvent(status="Conversion completed."))
229                return
230
[a58706d]231        except Exception as ex:
232            msg = str(ex)
233            wx.PostEvent(self.parent.manager.parent,
234                StatusEvent(status=msg, info='error'))
235            return
236
[535e181]237        frames = []
238        increment = 1
239        single_file = True
[05595c4]240        n_frames = iqdata.shape[0]
[535e181]241        # Standard file has 3 frames: SAS, calibration and WAS
[05595c4]242        if n_frames > 3:
[535e181]243            # File has multiple frames
[05595c4]244            params = self.ask_frame_range(n_frames)
[535e181]245            frames = params['frames']
246            increment = params['inc']
247            single_file = params['file']
248            if frames == []: return
249        else: # Only interested in SAS data
250            frames = [0]
251
[f2b3f28]252        output_path = self.output.GetPath()
253
[d112c30]254        if self.run is None:
[503cc34]255            self.run = []
[d112c30]256        elif not isinstance(self.run, list):
257            self.run = [self.run]
[503cc34]258
[ea2a7348]259        if self.title is None:
260            self.title = ''
261
[503cc34]262        metadata = {
263            'title': self.title,
264            'run': self.run,
265            'intrument': self.instrument,
266            'detector': [self.detector],
267            'sample': self.sample,
268            'source': self.source
269        }
[f2b3f28]270
[eb8da5f]271        frame_data = []
272        for i in frames:
273            data = Data1D(x=qdata, y=iqdata[i])
274            frame_data.append(data)
[94f4518]275        if single_file:
276            # Only need to set metadata on first Data1D object
277            frame_data[0].filename = output_path.split('\\')[-1]
278            for key, value in metadata.iteritems():
279                setattr(frame_data[0], key, value)
280        else:
281            # Need to set metadata for all Data1D objects
282            for datainfo in frame_data:
283                datainfo.filename = output_path.split('\\')[-1]
284                for key, value in metadata.iteritems():
285                    setattr(datainfo, key, value)
286
287
288        self.convert_to_cansas(frame_data, output_path, single_file)
[a58706d]289        wx.PostEvent(self.parent.manager.parent,
290            StatusEvent(status="Conversion completed."))
291
[11794f2]292    def on_help(self, event):
293        tree_location = ("user/sasgui/perspectives/file_converter/"
294            "file_converter_help.html")
295        doc_viewer = DocumentationWindow(self, -1, tree_location,
296            "", "File Converter Help")
297
[fdbea3c]298    def validate_inputs(self):
299        msg = "You must select a"
[535e181]300        if self.q_input.GetPath() == '' and self.data_type != 'bsl':
[fdbea3c]301            msg += " Q Axis input file."
302        elif self.iq_input.GetPath() == '':
303            msg += "n Intensity input file."
304        elif self.output.GetPath() == '':
305            msg += "destination for the converted file."
306        if msg != "You must select a":
307            wx.PostEvent(self.parent.manager.parent,
308                StatusEvent(status=msg, info='error'))
309            return
310
311        return True
312
[af84162]313    def show_detector_window(self, event):
[de0df2c]314        if self.meta_frames != []:
315            for frame in self.meta_frames:
316                frame.panel.on_close()
317        detector_frame = MetadataWindow(DetectorPanel,
318            parent=self.parent.manager.parent, manager=self,
[503cc34]319            metadata=self.detector, title='Detector Metadata')
[de0df2c]320        self.meta_frames.append(detector_frame)
321        self.parent.manager.put_icon(detector_frame)
322        detector_frame.Show(True)
[fdbea3c]323
[2a7722b]324    def show_sample_window(self, event):
325        if self.meta_frames != []:
326            for frame in self.meta_frames:
327                frame.panel.on_close()
328        sample_frame = MetadataWindow(SamplePanel,
329            parent=self.parent.manager.parent, manager=self,
[503cc34]330            metadata=self.sample, title='Sample Metadata')
[2a7722b]331        self.meta_frames.append(sample_frame)
332        self.parent.manager.put_icon(sample_frame)
333        sample_frame.Show(True)
334
[55bc56bc]335    def show_source_window(self, event):
336        if self.meta_frames != []:
337            for frame in self.meta_frames:
338                frame.panel.on_close()
339        source_frame = MetadataWindow(SourcePanel,
340            parent=self.parent.manager.parent, manager=self,
[503cc34]341            metadata=self.source, title="Source Metadata")
[55bc56bc]342        self.meta_frames.append(source_frame)
343        self.parent.manager.put_icon(source_frame)
344        source_frame.Show(True)
345
[a027549]346    def on_collapsible_pane(self, event):
347        self.Freeze()
348        self.SetupScrolling()
349        self.parent.Layout()
350        self.Thaw()
351
[4b862c4]352    def datatype_changed(self, event):
353        event.Skip()
354        dtype = event.GetEventObject().GetName()
355        self.data_type = dtype
[535e181]356        if dtype == 'bsl':
[05595c4]357            self.q_input.SetPath("")
[535e181]358            self.q_input.Disable()
359        else:
360            self.q_input.Enable()
[4b862c4]361
[55775e8]362    def radiationtype_changed(self, event):
363        event.Skip()
364        rtype = event.GetEventObject().GetValue().lower()
[503cc34]365        self.source.radiation = rtype
[55775e8]366
[f2b3f28]367    def metadata_changed(self, event):
368        event.Skip()
369        textbox = event.GetEventObject()
370        attr = textbox.GetName()
371        value = textbox.GetValue().strip()
[fdbea3c]372
[503cc34]373        if value == '': value = None
374
375        setattr(self, attr, value)
[f2b3f28]376
377
[77d92cd]378    def _do_layout(self):
[f2b3f28]379        vbox = wx.BoxSizer(wx.VERTICAL)
[a58706d]380
[13b9a63]381        instructions = ("Select either single column ASCII files or BSL/OTOKO"
382            " files containing the Q-Axis and Intensity-axis data, chose where"
383            " to save the converted file, then click Convert to convert them "
384            "to CanSAS XML format. If required, metadata can also be input "
385            "below.")
[5afe77f]386        instruction_label = wx.StaticText(self, -1, instructions,
387            size=(_STATICBOX_WIDTH+40, -1))
388        instruction_label.Wrap(_STATICBOX_WIDTH+40)
[f2b3f28]389        vbox.Add(instruction_label, flag=wx.TOP | wx.LEFT | wx.RIGHT, border=5)
[77d92cd]390
[a58706d]391        section = wx.StaticBox(self, -1)
392        section_sizer = wx.StaticBoxSizer(section, wx.VERTICAL)
393        section_sizer.SetMinSize((_STATICBOX_WIDTH, -1))
[77d92cd]394
395        input_grid = wx.GridBagSizer(5, 5)
396
[4b862c4]397        y = 0
398
[13b9a63]399        q_label = wx.StaticText(self, -1, "Q-Axis Data: ")
[4b862c4]400        input_grid.Add(q_label, (y,0), (1,1), wx.ALIGN_CENTER_VERTICAL, 5)
[a58706d]401
402        self.q_input = wx.FilePickerCtrl(self, -1,
403            size=(_STATICBOX_WIDTH-80, -1),
[13b9a63]404            message="Chose the Q-Axis data file.")
[4b862c4]405        input_grid.Add(self.q_input, (y,1), (1,1), wx.ALL, 5)
406        y += 1
[a58706d]407
[13b9a63]408        iq_label = wx.StaticText(self, -1, "Intensity-Axis Data: ")
[4b862c4]409        input_grid.Add(iq_label, (y,0), (1,1), wx.ALIGN_CENTER_VERTICAL, 5)
[a58706d]410
411        self.iq_input = wx.FilePickerCtrl(self, -1,
412            size=(_STATICBOX_WIDTH-80, -1),
[13b9a63]413            message="Chose the Intensity-Axis data file.")
[4b862c4]414        input_grid.Add(self.iq_input, (y,1), (1,1), wx.ALL, 5)
415        y += 1
416
417        data_type_label = wx.StaticText(self, -1, "Input Format: ")
418        input_grid.Add(data_type_label, (y,0), (1,1),
419            wx.ALIGN_CENTER_VERTICAL, 5)
420        radio_sizer = wx.BoxSizer(wx.HORIZONTAL)
421        ascii_btn = wx.RadioButton(self, -1, "ASCII", name="ascii",
422            style=wx.RB_GROUP)
423        ascii_btn.Bind(wx.EVT_RADIOBUTTON, self.datatype_changed)
424        radio_sizer.Add(ascii_btn)
[535e181]425        otoko_btn = wx.RadioButton(self, -1, "OTOKO 1D", name="otoko")
426        otoko_btn.Bind(wx.EVT_RADIOBUTTON, self.datatype_changed)
427        radio_sizer.Add(otoko_btn)
428        input_grid.Add(radio_sizer, (y,1), (1,1), wx.ALL, 5)
429        bsl_btn = wx.RadioButton(self, -1, "BSL 2D", name="bsl")
[4b862c4]430        bsl_btn.Bind(wx.EVT_RADIOBUTTON, self.datatype_changed)
431        radio_sizer.Add(bsl_btn)
432        y += 1
[a58706d]433
[55775e8]434        radiation_label = wx.StaticText(self, -1, "Radiation Type: ")
435        input_grid.Add(radiation_label, (y,0), (1,1), wx.ALL, 5)
436        radiation_input = wx.ComboBox(self, -1,
437            choices=["Neutron", "X-Ray", "Muon", "Electron"],
438            name="radiation", style=wx.CB_READONLY, value="Neutron")
439        radiation_input.Bind(wx.EVT_COMBOBOX, self.radiationtype_changed)
440        input_grid.Add(radiation_input, (y,1), (1,1))
441        y += 1
442
[a58706d]443        output_label = wx.StaticText(self, -1, "Output File: ")
[4b862c4]444        input_grid.Add(output_label, (y,0), (1,1), wx.ALIGN_CENTER_VERTICAL, 5)
[a58706d]445
446        self.output = wx.FilePickerCtrl(self, -1,
447            size=(_STATICBOX_WIDTH-80, -1),
[55775e8]448            message="Chose where to save the output file.",
[a58706d]449            style=wx.FLP_SAVE | wx.FLP_OVERWRITE_PROMPT | wx.FLP_USE_TEXTCTRL,
[05595c4]450            wildcard="CanSAS 1D (*.xml)|*.xml|Red2D (*.dat)|*.dat")
[4b862c4]451        input_grid.Add(self.output, (y,1), (1,1), wx.ALL, 5)
452        y += 1
[a58706d]453
[fdbea3c]454        convert_btn = wx.Button(self, wx.ID_OK, "Convert")
[4b862c4]455        input_grid.Add(convert_btn, (y,0), (1,1), wx.ALL, 5)
[a58706d]456        convert_btn.Bind(wx.EVT_BUTTON, self.on_convert)
[77d92cd]457
[11794f2]458        help_btn = wx.Button(self, -1, "HELP")
459        input_grid.Add(help_btn, (y,1), (1,1), wx.ALL, 5)
460        help_btn.Bind(wx.EVT_BUTTON, self.on_help)
461
[a58706d]462        section_sizer.Add(input_grid)
[77d92cd]463
[f2b3f28]464        vbox.Add(section_sizer, flag=wx.ALL, border=5)
465
466        metadata_section = wx.CollapsiblePane(self, -1, "Metadata",
[fdbea3c]467            size=(_STATICBOX_WIDTH+40, -1), style=wx.WS_EX_VALIDATE_RECURSIVELY)
468        metadata_pane = metadata_section.GetPane()
[f2b3f28]469        metadata_grid = wx.GridBagSizer(5, 5)
470
[a027549]471        metadata_section.Bind(wx.EVT_COLLAPSIBLEPANE_CHANGED,
472            self.on_collapsible_pane)
473
[f2b3f28]474        y = 0
[503cc34]475        for item in self.properties:
[7c8ddb83]476            # Capitalise each word
477            label_txt = " ".join(
478                [s.capitalize() for s in item.replace('_', ' ').split(' ')])
479            if item == 'run':
480                label_txt = "Run Number"
[fdbea3c]481            label = wx.StaticText(metadata_pane, -1, label_txt,
[f2b3f28]482                style=wx.ALIGN_CENTER_VERTICAL)
[fdbea3c]483            input_box = wx.TextCtrl(metadata_pane, name=item,
[f2b3f28]484                size=(_STATICBOX_WIDTH-80, -1))
485            input_box.Bind(wx.EVT_TEXT, self.metadata_changed)
486            metadata_grid.Add(label, (y,0), (1,1),
487                wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
[fdbea3c]488            metadata_grid.Add(input_box, (y,1), (1,2), wx.EXPAND)
[f2b3f28]489            y += 1
490
[fdbea3c]491        detector_label = wx.StaticText(metadata_pane, -1,
492            "Detector:")
493        metadata_grid.Add(detector_label, (y, 0), (1,1), wx.ALL | wx.EXPAND, 5)
[af84162]494        detector_btn = wx.Button(metadata_pane, -1, "Enter Detector Metadata")
495        metadata_grid.Add(detector_btn, (y, 1), (1,1), wx.ALL | wx.EXPAND, 5)
496        detector_btn.Bind(wx.EVT_BUTTON, self.show_detector_window)
[fdbea3c]497        y += 1
498
[2a7722b]499        sample_label = wx.StaticText(metadata_pane, -1, "Sample: ")
500        metadata_grid.Add(sample_label, (y,0), (1,1), wx.ALL | wx.EXPAND, 5)
501        sample_btn = wx.Button(metadata_pane, -1, "Enter Sample Metadata")
502        metadata_grid.Add(sample_btn, (y,1), (1,1), wx.ALL | wx.EXPAND, 5)
503        sample_btn.Bind(wx.EVT_BUTTON, self.show_sample_window)
504        y += 1
505
[55bc56bc]506        source_label = wx.StaticText(metadata_pane, -1, "Source: ")
507        metadata_grid.Add(source_label, (y,0), (1,1), wx.ALL | wx.EXPAND, 5)
508        source_btn = wx.Button(metadata_pane, -1, "Enter Source Metadata")
509        source_btn.Bind(wx.EVT_BUTTON, self.show_source_window)
510        metadata_grid.Add(source_btn, (y,1), (1,1), wx.ALL | wx.EXPAND, 5)
511        y += 1
512
[fdbea3c]513        metadata_pane.SetSizer(metadata_grid)
[f2b3f28]514
515        vbox.Add(metadata_section, proportion=0, flag=wx.ALL, border=5)
[77d92cd]516
517        vbox.Fit(self)
518        self.SetSizer(vbox)
519
520class ConverterWindow(widget.CHILD_FRAME):
521
522    def __init__(self, parent=None, title='File Converter', base=None,
[a027549]523        manager=None, size=(PANEL_SIZE * 1.05, PANEL_SIZE / 1.25),
[77d92cd]524        *args, **kwargs):
525        kwargs['title'] = title
526        kwargs['size'] = size
527        widget.CHILD_FRAME.__init__(self, parent, *args, **kwargs)
528
529        self.manager = manager
530        self.panel = ConverterPanel(self, base=None)
531        self.Bind(wx.EVT_CLOSE, self.on_close)
532        self.SetPosition((wx.LEFT, PANEL_TOP))
533        self.Show(True)
534
535    def on_close(self, event):
536        if self.manager is not None:
537            self.manager.converter_frame = None
538        self.Destroy()
Note: See TracBrowser for help on using the repository browser.