Index: src/sas/sasgui/perspectives/file_converter/converter_panel.py
===================================================================
--- src/sas/sasgui/perspectives/file_converter/converter_panel.py	(revision 3331e11ae1f2cdf244e5073a82c0437c4a818de2)
+++ src/sas/sasgui/perspectives/file_converter/converter_panel.py	(revision af84162d85c167ebb54e6a6f87a2a2bf3b62fd8b)
@@ -10,4 +10,5 @@
 from sas.sasgui.perspectives.calculator import calculator_widgets as widget
 from sas.sasgui.perspectives.file_converter.converter_widgets import VectorInput
+from sas.sasgui.perspectives.file_converter.detector_panel import DetectorWindow
 from sas.sasgui.guiframe.events import StatusEvent
 from sas.sasgui.guiframe.dataFitting import Data1D
@@ -41,4 +42,5 @@
         self.base = base
         self.parent = parent
+        self.detector_frame = None
 
         self.q_input = None
@@ -180,4 +182,12 @@
         return True
 
+    def show_detector_window(self, event):
+        if self.detector_frame is not None:
+            self.detector_frame.panel.on_close()
+            return
+        self.detector_frame = DetectorWindow(self.parent.manager.parent,
+            manager=self, detector=self.metadata['detector'][0])
+        self.parent.manager.put_icon(self.detector_frame)
+        self.detector_frame.Show(True)
 
     def metadata_changed(self, event):
@@ -282,72 +292,8 @@
             "Detector:")
         metadata_grid.Add(detector_label, (y, 0), (1,1), wx.ALL | wx.EXPAND, 5)
+        detector_btn = wx.Button(metadata_pane, -1, "Enter Detector Metadata")
+        metadata_grid.Add(detector_btn, (y, 1), (1,1), wx.ALL | wx.EXPAND, 5)
+        detector_btn.Bind(wx.EVT_BUTTON, self.show_detector_window)
         y += 1
-
-        name_label = wx.StaticText(metadata_pane, -1, "Name: ")
-        metadata_grid.Add(name_label, (y, 1), (1,1))
-
-        name_input = wx.TextCtrl(metadata_pane,
-            name="detector_name", size=(_STATICBOX_WIDTH-80-55, -1))
-        metadata_grid.Add(name_input, (y, 2), (1,1))
-        name_input.Bind(wx.EVT_TEXT, self.metadata_changed)
-        y += 1
-
-        distance_label = wx.StaticText(metadata_pane, -1,
-            "Distance (mm): ")
-        metadata_grid.Add(distance_label, (y, 1), (1,1))
-
-        distance_input = wx.TextCtrl(metadata_pane, -1,
-            name="detector_distance", size=(50,-1))
-        metadata_grid.Add(distance_input, (y,2), (1,1))
-        self.to_validate.append(distance_input)
-        distance_input.Bind(wx.EVT_TEXT, self.metadata_changed)
-        y += 1
-
-        offset_label = wx.StaticText(metadata_pane, -1,
-            "Offset (m): ")
-        metadata_grid.Add(offset_label, (y,1), (1,1))
-
-        offset_input = VectorInput(metadata_pane, "detector_offset",
-            callback=self.metadata_changed)
-        self.to_validate.append(offset_input)
-        metadata_grid.Add(offset_input.GetSizer(), (y,2), (1,1), wx.BOTTOM, 5)
-        y += 1
-
-        orientation_label = wx.StaticText(metadata_pane, -1,
-            u"Orientation (\xb0): ")
-        metadata_grid.Add(orientation_label, (y, 1), (1, 1))
-
-        orientation_input = VectorInput(metadata_pane, "detector_orientation",
-            callback=self.metadata_changed, z_enabled=True,
-            labels=["Roll: ", "Pitch: ", "Yaw: "])
-        self.to_validate.append(orientation_input)
-        metadata_grid.Add(orientation_input.GetSizer(),
-            (y,2), (1,1), wx.BOTTOM, 5)
-        y += 1
-
-        pixel_label = wx.StaticText(metadata_pane, -1, "Pixel Size (mm): ")
-        metadata_grid.Add(pixel_label, (y,1), (1,1))
-
-        pixel_input = VectorInput(metadata_pane, "detector_pixel_size",
-             callback=self.metadata_changed)
-        self.to_validate.append(pixel_input)
-        metadata_grid.Add(pixel_input.GetSizer(), (y,2), (1,1), wx.BOTTOM, 5)
-        y += 1
-
-        beam_label = wx.StaticText(metadata_pane, -1, "Beam Center (mm): ")
-        metadata_grid.Add(beam_label, (y,1), (1,1))
-        beam_input = VectorInput(metadata_pane, "detector_beam_center",
-            callback=self.metadata_changed)
-        self.to_validate.append(beam_input)
-        metadata_grid.Add(beam_input.GetSizer(), (y,2), (1,1), wx.BOTTOM, 5)
-        y += 1
-
-        slit_label = wx.StaticText(metadata_pane, -1, "Slit Length (mm): ")
-        metadata_grid.Add(slit_label, (y,1), (1,1))
-        slit_input = wx.TextCtrl(metadata_pane, -1, size=(50,-1),
-            name="detector_slit_length")
-        self.to_validate.append(slit_input)
-        slit_input.Bind(wx.EVT_TEXT, self.metadata_changed)
-        metadata_grid.Add(slit_input, (y,2), (1,1), wx.BOTTOM, 5)
 
         metadata_pane.SetSizer(metadata_grid)
Index: src/sas/sasgui/perspectives/file_converter/converter_widgets.py
===================================================================
--- src/sas/sasgui/perspectives/file_converter/converter_widgets.py	(revision c9a519f7daec51667fa6d6607d49929fee6c8b03)
+++ src/sas/sasgui/perspectives/file_converter/converter_widgets.py	(revision af84162d85c167ebb54e6a6f87a2a2bf3b62fd8b)
@@ -25,4 +25,6 @@
         self.control_name = control_name
         self._callback = callback
+        self._name = control_name
+
         self.labels = labels
         self.z_enabled = z_enabled
@@ -40,4 +42,7 @@
         return self._sizer
 
+    def GetName(self):
+        return self._name
+
     def GetValue(self):
         """
@@ -48,5 +53,5 @@
         v = Vector()
         if not self.Validate(): return v
-        for direction, control in self._inputs:
+        for direction, control in self._inputs.iteritems():
             try:
                 value = float(control.GetValue())
@@ -57,12 +62,22 @@
         return v
 
+    def SetValue(self, vector):
+        directions = ['x', 'y']
+        if self.z_enabled: directions.append('z')
+        for direction in directions:
+            value = getattr(vector, direction)
+            if value is None: value = ''
+            self._inputs[direction].SetValue(str(value))
+
     def Validate(self):
         """
         Validate the contents of the inputs
 
-        :return control_valid: Whether or not the inputs are valid
-        :return invalid_control: The control that is not valid
+        :return all_valid: Whether or not the inputs are valid
+        :return invalid_ctrl: A control that is not valid
             (or None if all are valid)
         """
+        all_valid = True
+        invalid_ctrl = None
         for control in self._inputs.values():
             if control.GetValue() == '': continue
@@ -70,6 +85,7 @@
             control_valid = check_float(control)
             if not control_valid:
-                return False, control
-        return True, None
+                all_valid = False
+                invalid_ctrl = control
+        return all_valid, invalid_ctrl
 
 
@@ -85,5 +101,5 @@
         x_input.Bind(wx.EVT_TEXT, self._callback)
 
-        self._sizer.AddSpacer((15, -1))
+        self._sizer.AddSpacer((10, -1))
 
         y_label = wx.StaticText(self.parent, -1, self.labels[1],
@@ -97,5 +113,5 @@
 
         if self.z_enabled:
-            self._sizer.AddSpacer((15, -1))
+            self._sizer.AddSpacer((10, -1))
 
             z_label = wx.StaticText(self.parent, -1, self.labels[2],
Index: src/sas/sasgui/perspectives/file_converter/detector_panel.py
===================================================================
--- src/sas/sasgui/perspectives/file_converter/detector_panel.py	(revision af84162d85c167ebb54e6a6f87a2a2bf3b62fd8b)
+++ src/sas/sasgui/perspectives/file_converter/detector_panel.py	(revision af84162d85c167ebb54e6a6f87a2a2bf3b62fd8b)
@@ -0,0 +1,176 @@
+import wx
+import sys
+from sas.sasgui.perspectives.calculator import calculator_widgets as widget
+from sas.sasgui.perspectives.file_converter.converter_widgets import VectorInput
+from wx.lib.scrolledpanel import ScrolledPanel
+from sas.sasgui.guiframe.panel_base import PanelBase
+from sas.sascalc.dataloader.data_info import Detector
+from sas.sasgui.guiframe.events import StatusEvent
+from sas.sasgui.guiframe.utils import check_float
+
+if sys.platform.count("win32") > 0:
+    PANEL_TOP = 0
+    _STATICBOX_WIDTH = 350
+    PANEL_SIZE = 440
+    FONT_VARIANT = 0
+else:
+    PANEL_TOP = 60
+    _STATICBOX_WIDTH = 380
+    PANEL_SIZE = 470
+    FONT_VARIANT = 1
+
+class DetectorPanel(ScrolledPanel, PanelBase):
+
+    def __init__(self, parent, detector, base=None, *args, **kwargs):
+        ScrolledPanel.__init__(self, parent, *args, **kwargs)
+        PanelBase.__init__(self)
+        self.SetupScrolling()
+        self.SetWindowVariant(variant=FONT_VARIANT)
+
+        if detector.name is None:
+            detector.name = ''
+
+        self.base = base
+        self.parent = parent
+        self.detector = detector
+        self._to_validate = []
+        self._vectors = []
+
+        self._do_layout()
+        self.SetAutoLayout(True)
+        self.Layout()
+
+    def on_change(self, event):
+        ctrl = event.GetEventObject()
+        value = ctrl.GetValue()
+        if value == '': value = None
+        setattr(self.detector, ctrl.GetName(), value)
+
+    def on_close(self, event=None):
+        for ctrl in self._to_validate:
+            ctrl.SetBackgroundColour(wx.WHITE)
+            if ctrl.GetValue() == '': continue
+            if not check_float(ctrl):
+                msg = "{} must be a valid float".format(
+                    ctrl.GetName().replace("_", " "))
+                wx.PostEvent(self.parent.manager.parent.manager.parent,
+                    StatusEvent(status=msg, info='error'))
+                return
+        for vector_in in self._vectors:
+            is_valid, invalid_ctrl = vector_in.Validate()
+            if not is_valid:
+                msg = "{} must be a valid float".format(
+                    invalid_ctrl.GetName().replace("_", " "))
+                wx.PostEvent(self.parent.manager.parent.manager.parent,
+                    StatusEvent(status=msg, info='error'))
+                return
+            setattr(self.detector, vector_in.GetName(), vector_in.GetValue())
+
+        self.parent.on_close(event)
+
+    def _do_layout(self):
+        vbox = wx.BoxSizer(wx.VERTICAL)
+
+        section = wx.StaticBox(self, -1, "Detector")
+        section_sizer = wx.StaticBoxSizer(section, wx.VERTICAL)
+        section_sizer.SetMinSize((_STATICBOX_WIDTH, -1))
+
+        input_grid = wx.GridBagSizer(5, 5)
+
+        y = 0
+        name_label = wx.StaticText(self, -1, "Name: ")
+        input_grid.Add(name_label, (y,0), (1,1), wx.ALL, 5)
+        name_input = wx.TextCtrl(self, -1, name="name")
+        input_grid.Add(name_input, (y,1), (1,1))
+        name_input.Bind(wx.EVT_TEXT, self.on_change)
+        y += 1
+
+        distance_label = wx.StaticText(self, -1,
+            "Distance (mm): ")
+        input_grid.Add(distance_label, (y, 0), (1,1), wx.ALL, 5)
+        distance_input = wx.TextCtrl(self, -1,
+            name="distance", size=(50,-1))
+        input_grid.Add(distance_input, (y,1), (1,1))
+        distance_input.Bind(wx.EVT_TEXT, self.on_change)
+        self._to_validate.append(distance_input)
+        y += 1
+
+        offset_label = wx.StaticText(self, -1, "Offset (mm): ")
+        input_grid.Add(offset_label, (y,0), (1,1), wx.ALL, 5)
+        offset_input = VectorInput(self, "offset")
+        input_grid.Add(offset_input.GetSizer(), (y,1), (1,1))
+        self._vectors.append(offset_input)
+        y += 1
+
+        orientation_label = wx.StaticText(self, -1, "Orientation (\xb0): ")
+        input_grid.Add(orientation_label, (y,0), (1,1), wx.ALL, 5)
+        orientation_input = VectorInput(self, "orientation", z_enabled=True,
+            labels=["Roll: ", "Pitch: ", "Yaw: "])
+        input_grid.Add(orientation_input.GetSizer(), (y,1), (1,1))
+        self._vectors.append(orientation_input)
+        y += 1
+
+        pixel_label = wx.StaticText(self, -1, "Pixel Size (mm): ")
+        input_grid.Add(pixel_label, (y,0), (1,1), wx.ALL, 5)
+        pixel_input = VectorInput(self, "pixel_size")
+        input_grid.Add(pixel_input.GetSizer(), (y,1), (1,1))
+        self._vectors.append(pixel_input)
+        y += 1
+
+        beam_label = wx.StaticText(self, -1, "Beam Center (mm): ")
+        input_grid.Add(beam_label, (y,0), (1,1), wx.ALL, 5)
+        beam_input = VectorInput(self, "beam_center")
+        input_grid.Add(beam_input.GetSizer(), (y,1), (1,1))
+        self._vectors.append(beam_input)
+        y += 1
+
+        slit_label = wx.StaticText(self, -1, "Slit Length (mm): ")
+        input_grid.Add(slit_label, (y,0), (1,1), wx.ALL, 5)
+        slit_input = wx.TextCtrl(self, -1, name="slit_length", size=(50,-1))
+        input_grid.Add(slit_input, (y,1), (1,1))
+        slit_input.Bind(wx.EVT_TEXT, self.on_change)
+        self._to_validate.append(slit_input)
+        y += 1
+
+        done_btn = wx.Button(self, -1, "Done")
+        input_grid.Add(done_btn, (y,0), (1,1), wx.ALL, 5)
+        done_btn.Bind(wx.EVT_BUTTON, self.on_close)
+
+        section_sizer.Add(input_grid)
+        vbox.Add(section_sizer, flag=wx.ALL, border=10)
+
+        name_input.SetValue(self.detector.name)
+        distance = self.detector.distance
+        if distance is None: distance = ''
+        elif '.' not in distance: distance += '.0'
+        distance_input.SetValue(str(distance))
+        offset_input.SetValue(self.detector.offset)
+        orientation_input.SetValue(self.detector.orientation)
+        pixel_input.SetValue(self.detector.pixel_size)
+        beam_input.SetValue(self.detector.beam_center)
+        slit_len = self.detector.slit_length
+        if slit_len is None: slit_len = ''
+        elif '.' not in slit_len: slit_len += '.0'
+        slit_input.SetValue(slit_len)
+
+        vbox.Fit(self)
+        self.SetSizer(vbox)
+
+class DetectorWindow(widget.CHILD_FRAME):
+
+    def __init__(self, parent=None, title='Detector Metadata', base=None,
+        manager=None, size=(PANEL_SIZE, PANEL_SIZE*0.8), detector=None,
+         *args, **kwargs):
+        kwargs['title'] = title
+        kwargs['size'] = size
+        widget.CHILD_FRAME.__init__(self, parent, *args, **kwargs)
+
+        self.manager = manager
+        self.panel = DetectorPanel(self, detector, base=None)
+        self.Bind(wx.EVT_CLOSE, self.on_close)
+
+    def on_close(self, event):
+        if self.manager is not None:
+            self.manager.detector_frame = None
+            self.manager.metadata['detector'] = [self.panel.detector]
+        self.Destroy()
