]> gitweb @ CieloNegro.org - task-reporter.git/blobdiff - src/main/scala/jp/ymir/taskReporter/ui/MainFrame.scala
wip
[task-reporter.git] / src / main / scala / jp / ymir / taskReporter / ui / MainFrame.scala
index 4b31c01270822fe6476d1756514a2a991e8245a2..a09aa5dfa6f2b655ce8c67dc71c1f7a30973b298 100644 (file)
 package jp.ymir.taskReporter.ui
 import java.awt.Dimension
+import java.awt.event.ComponentAdapter
+import java.awt.event.ComponentEvent
 import java.io._
 import javax.swing.JOptionPane
+import javax.swing.JSplitPane
 import javax.swing.KeyStroke
 import javax.swing.event.MenuListener
 import javax.swing.event.MenuEvent
+import javax.swing.filechooser.FileNameExtensionFilter
 import jp.ymir.taskReporter._
 import jp.ymir.taskReporter.core._
 import scala.swing._
+import scala.swing.Swing._
 import scala.swing.event._
 
 class MainFrame(reportFile: Option[File]) extends Frame {
-  private val reportSet: ReportSet = new ReportSet(reportFile)
+  frame =>
 
-  title = "Task Reporter" + Main.getVersion
+  private val reportSet = new ReportSet(reportFile)
+
+  title         = "Task Reporter " + Main.getVersion
+  preferredSize = Preferences.mainFrameSize()
+
+  case class FileOpened(file: File)         extends Event
+  case class ReportSelected(report: Report) extends Event
+  case class ReportDeselected()             extends Event
+  case class TaskSelected(task: Task)       extends Event
+  case class TaskDeselected()               extends Event
+
+  peer.addComponentListener(new ComponentAdapter() {
+    override def componentResized(e: ComponentEvent) {
+      Preferences.mainFrameSize() = size
+    }
+  })
+
+  menuBar = new MenuBar {
+    contents += new Menu("File") {
+      mnemonic = Key.F
+
+      val miOpen = new MenuItem(new Action("Open...") {
+        accelerator = Some(KeyStroke getKeyStroke "control O")
+        def apply {
+          val chooser = new FileChooser(Preferences.lastChosenDir()) {
+            fileSelectionMode = FileChooser.SelectionMode.FilesOnly
+            fileFilter        = new FileNameExtensionFilter("TSV files", "tsv")
+            title             = "Select a report file to open..."
+            peer.setAcceptAllFileFilterUsed(false)
+          }
+          val r = chooser.showOpenDialog(null)
+          if (r == FileChooser.Result.Approve) {
+            val file = chooser.selectedFile
+            Preferences.lastChosenDir() = file.getParentFile
+            reportSet load file
+            frame publish FileOpened(file)
+          }
+        }
+      })
+      contents += miOpen
+
+      val miSave = new MenuItem(new Action("Save") {
+        accelerator = Some(KeyStroke.getKeyStroke("control S"));
+        def apply = save
+      })
+      contents += miSave
+
+      contents += new Separator
+
+      contents += new MenuItem(new Action("Quit") {
+        accelerator = Some(KeyStroke.getKeyStroke("control Q"))
+        def apply = closeOperation
+      })
+
+      peer.addMenuListener(new MenuListener {
+        def menuSelected(e: MenuEvent) {
+          miOpen.enabled = !dirty
+          miSave.enabled = dirty
+          miSave.text    =
+            if (reportSet.file.isEmpty)
+              "Save..."
+            else
+              "Save"
+        }
+        def menuDeselected(e: MenuEvent) {}
+        def menuCanceled(e: MenuEvent) {}
+      })
+    }
+  }
+
+  contents = new SplitPane {
+    peer.setOrientation(JSplitPane.HORIZONTAL_SPLIT)
+    continuousLayout   = true
+    oneTouchExpandable = true
+    resizeWeight       = 0 // Let the left pane be fixed
+
+    rightComponent = new BoxPanel(Orientation.Vertical) {
+      border = EmptyBorder(5, 5, 5, 5)
+
+      contents += new ScrollPane(
+        new Table() {
+          peer setFillsViewportHeight true
+          listenTo(frame)
+
+          override def model : Report = super.model.asInstanceOf[Report]
+
+          reactions += {
+            case ReportSelected(report) =>
+              model = report
+              if (rowCount > 0) {
+                selection.rows += rowCount - 1 // Select the last report
+              }
+            case ReportDeselected() =>
+              model = new Report() // Empty report
+          }
+
+          selection.reactions += {
+            case TableRowsSelected(_, _, false) =>
+              selection.rows.size match {
+                case 1 =>
+                  val task = model(selection.rows.head)
+                  frame publish TaskSelected(task)
+                case _ =>
+                  frame publish TaskDeselected()
+              }
+          }
+        })
+      contents += VStrut(5)
+      contents += new Separator(Orientation.Horizontal)
+      contents += VStrut(5)
+      contents += new TaskEditor
+      contents += VStrut(5)
+      contents += new Separator(Orientation.Horizontal)
+      contents += VStrut(5)
+      contents += new FlowPanel(FlowPanel.Alignment.Left)() {
+        contents += new Button(new Action("New") {
+          def apply = {} // FIXME
+        })
+        contents += new Button(new Action("Delete...") {
+          def apply = {} // FIXME
+        })
+      }
+    }
+
+    leftComponent = new BorderPanel {
+      border = EmptyBorder(5, 5, 5, 5)
+
+      add(
+        new ScrollPane(
+          new Table() {
+            peer setFillsViewportHeight true
+            peer setModel reportSet
+            listenTo(frame)
+            reactions += {
+              case FileOpened(f) =>
+                if (rowCount > 0) {
+                  selection.rows += rowCount - 1 // Select the last report
+                }
+            }
+            selection.reactions += {
+              case TableRowsSelected(_, _, false) =>
+                selection.rows.size match {
+                  case 1 =>
+                    val report = reportSet(selection.rows.head)
+                    frame publish ReportSelected(report)
+                  case _ =>
+                    frame publish ReportDeselected()
+                }
+            }
+          }), BorderPanel.Position.Center)
+
+      add(
+        new FlowPanel(FlowPanel.Alignment.Left)() {
+          contents += new Button(new Action("New...") {
+            def apply = {} // FIXME
+          })
+          contents += new Button(new Action("Delete...") {
+            def apply = {} // FIXME
+          })
+        }, BorderPanel.Position.South)
+
+      preferredSize = minimumSize
+    }
+  }
+
+  reportSet.file match {
+    case Some(file) => frame publish FileOpened(file)
+    case None       => frame publish ReportDeselected()
+  }
 
-  // FIXME: Provide a way to configure this.
-  size = new Dimension(640, 480)
   centerOnScreen
+  visible = true
 
   override def closeOperation {
     if (dirty) {
@@ -29,11 +201,8 @@ class MainFrame(reportFile: Option[File]) extends Frame {
         JOptionPane.YES_NO_CANCEL_OPTION);
 
       r match {
-        case JOptionPane.YES_OPTION =>
-          // FIXME
-          dispose
-        case JOptionPane.NO_OPTION =>
-          dispose
+        case JOptionPane.YES_OPTION => save; dispose
+        case JOptionPane.NO_OPTION  => dispose
         case _ =>
       }
     }
@@ -46,38 +215,33 @@ class MainFrame(reportFile: Option[File]) extends Frame {
     return reportSet.dirty
   }
 
-  menuBar = new MenuBar {
-    contents += new Menu("File") {
-      mnemonic = Key.F
+  def save {
+    if (reportSet.file.isEmpty) {
+      val chooser = new FileChooser(Preferences.lastChosenDir())
+      val r = chooser.showSaveDialog(null)
+      if (r != FileChooser.Result.Approve) {
+        return
+      }
 
-      contents += new MenuItem(new Action("Open...") {
-        accelerator = Some(KeyStroke.getKeyStroke("control O"))
-        def apply {
-          // FIXME
-        }
-      })
+      if (chooser.selectedFile.exists) {
+        val r = JOptionPane.showConfirmDialog(
+          peer,
+          "The chosen file or directory \"" + chooser.selectedFile.getName + "\" already exists.\n" +
+            "Do you want to overwrite it?",
+          "Confirmation",
+          JOptionPane.YES_NO_OPTION)
 
-      val save = new MenuItem(new Action("Save") {
-        accelerator = Some(KeyStroke.getKeyStroke("control S"));
-        def apply {
-          // FIXME
-        }
-      })
-      contents += save
-      peer.addMenuListener(new MenuListener {
-        def menuSelected(e: MenuEvent) {
-          save.enabled = dirty
-          save.text    =
-            if (reportSet.file.isEmpty)
-              "Save..."
-            else
-              "Save"
+        r match {
+          case JOptionPane.YES_OPTION =>
+          case JOptionPane.NO_OPTION  => return
         }
-        def menuDeselected(e: MenuEvent) {}
-        def menuCanceled(e: MenuEvent) {}
-      })
+      }
+
+      Preferences.lastChosenDir() = chooser.selectedFile.getParentFile
+      reportSet.save(chooser.selectedFile)
+    }
+    else {
+      reportSet.save
     }
   }
-
-  visible = true
 }