]> gitweb @ CieloNegro.org - task-reporter.git/blob - src/main/scala/jp/ymir/taskReporter/ui/MainFrame.scala
wip
[task-reporter.git] / src / main / scala / jp / ymir / taskReporter / ui / MainFrame.scala
1 package jp.ymir.taskReporter.ui
2 import java.awt.Dimension
3 import java.awt.event.ComponentAdapter
4 import java.awt.event.ComponentEvent
5 import java.io._
6 import javax.swing.JOptionPane
7 import javax.swing.JSplitPane
8 import javax.swing.KeyStroke
9 import javax.swing.event.MenuListener
10 import javax.swing.event.MenuEvent
11 import javax.swing.filechooser.FileNameExtensionFilter
12 import jp.ymir.taskReporter._
13 import jp.ymir.taskReporter.core._
14 import scala.swing._
15 import scala.swing.Swing._
16 import scala.swing.event._
17
18 class MainFrame(reportFile: Option[File]) extends Frame {
19   frame =>
20
21   private val reportSet = new ReportSet(reportFile)
22
23   title         = "Task Reporter " + Main.getVersion
24   preferredSize = Preferences.mainFrameSize()
25
26   case class FileOpened(file: File)         extends Event
27   case class ReportSelected(report: Report) extends Event
28   case class ReportDeselected()             extends Event
29   case class TaskSelected(task: Task)       extends Event
30   case class TaskDeselected()               extends Event
31
32   peer.addComponentListener(new ComponentAdapter() {
33     override def componentResized(e: ComponentEvent) {
34       Preferences.mainFrameSize() = size
35     }
36   })
37
38   menuBar = new MenuBar {
39     contents += new Menu("File") {
40       mnemonic = Key.F
41
42       val miOpen = new MenuItem(new Action("Open...") {
43         accelerator = Some(KeyStroke getKeyStroke "control O")
44         def apply {
45           val chooser = new FileChooser(Preferences.lastChosenDir()) {
46             fileSelectionMode = FileChooser.SelectionMode.FilesOnly
47             fileFilter        = new FileNameExtensionFilter("TSV files", "tsv")
48             title             = "Select a report file to open..."
49             peer.setAcceptAllFileFilterUsed(false)
50           }
51           val r = chooser.showOpenDialog(null)
52           if (r == FileChooser.Result.Approve) {
53             val file = chooser.selectedFile
54             Preferences.lastChosenDir() = file.getParentFile
55             reportSet load file
56             frame publish FileOpened(file)
57           }
58         }
59       })
60       contents += miOpen
61
62       val miSave = new MenuItem(new Action("Save") {
63         accelerator = Some(KeyStroke.getKeyStroke("control S"));
64         def apply = save
65       })
66       contents += miSave
67
68       contents += new Separator
69
70       contents += new MenuItem(new Action("Quit") {
71         accelerator = Some(KeyStroke.getKeyStroke("control Q"))
72         def apply = closeOperation
73       })
74
75       peer.addMenuListener(new MenuListener {
76         def menuSelected(e: MenuEvent) {
77           miOpen.enabled = !dirty
78           miSave.enabled = dirty
79           miSave.text    =
80             if (reportSet.file.isEmpty)
81               "Save..."
82             else
83               "Save"
84         }
85         def menuDeselected(e: MenuEvent) {}
86         def menuCanceled(e: MenuEvent) {}
87       })
88     }
89   }
90
91   contents = new SplitPane {
92     peer.setOrientation(JSplitPane.HORIZONTAL_SPLIT)
93     continuousLayout   = true
94     oneTouchExpandable = true
95     resizeWeight       = 0 // Let the left pane be fixed
96
97     rightComponent = new BoxPanel(Orientation.Vertical) {
98       border = EmptyBorder(5, 5, 5, 5)
99
100       contents += new ScrollPane(
101         new Table() {
102           peer setFillsViewportHeight true
103           listenTo(frame)
104
105           override def model : Report = super.model.asInstanceOf[Report]
106
107           reactions += {
108             case ReportSelected(report) =>
109               model = report
110               if (rowCount > 0) {
111                 selection.rows += rowCount - 1 // Select the last report
112               }
113             case ReportDeselected() =>
114               model = new Report() // Empty report
115           }
116
117           selection.reactions += {
118             case TableRowsSelected(_, _, false) =>
119               selection.rows.size match {
120                 case 1 =>
121                   val task = model(selection.rows.head)
122                   frame publish TaskSelected(task)
123                 case _ =>
124                   frame publish TaskDeselected()
125               }
126           }
127         })
128       contents += VStrut(5)
129       contents += new Separator(Orientation.Horizontal)
130       contents += VStrut(5)
131       contents += new TaskEditor
132       contents += VStrut(5)
133       contents += new Separator(Orientation.Horizontal)
134       contents += VStrut(5)
135       contents += new FlowPanel(FlowPanel.Alignment.Left)() {
136         contents += new Button(new Action("New") {
137           def apply = {} // FIXME
138         })
139         contents += new Button(new Action("Delete...") {
140           def apply = {} // FIXME
141         })
142       }
143     }
144
145     leftComponent = new BorderPanel {
146       border = EmptyBorder(5, 5, 5, 5)
147
148       add(
149         new ScrollPane(
150           new Table() {
151             peer setFillsViewportHeight true
152             peer setModel reportSet
153             listenTo(frame)
154             reactions += {
155               case FileOpened(f) =>
156                 if (rowCount > 0) {
157                   selection.rows += rowCount - 1 // Select the last report
158                 }
159             }
160             selection.reactions += {
161               case TableRowsSelected(_, _, false) =>
162                 selection.rows.size match {
163                   case 1 =>
164                     val report = reportSet(selection.rows.head)
165                     frame publish ReportSelected(report)
166                   case _ =>
167                     frame publish ReportDeselected()
168                 }
169             }
170           }), BorderPanel.Position.Center)
171
172       add(
173         new FlowPanel(FlowPanel.Alignment.Left)() {
174           contents += new Button(new Action("New...") {
175             def apply = {} // FIXME
176           })
177           contents += new Button(new Action("Delete...") {
178             def apply = {} // FIXME
179           })
180         }, BorderPanel.Position.South)
181
182       preferredSize = minimumSize
183     }
184   }
185
186   reportSet.file match {
187     case Some(file) => frame publish FileOpened(file)
188     case None       => frame publish ReportDeselected()
189   }
190
191   centerOnScreen
192   visible = true
193
194   override def closeOperation {
195     if (dirty) {
196       val r = JOptionPane.showConfirmDialog(
197         peer,
198         "The report file \"" + reportSet.file.get.getName + "\" has been modified.\n" +
199           "Do you want to save it before closing?",
200         "Confirmation",
201         JOptionPane.YES_NO_CANCEL_OPTION);
202
203       r match {
204         case JOptionPane.YES_OPTION => save; dispose
205         case JOptionPane.NO_OPTION  => dispose
206         case _ =>
207       }
208     }
209     else {
210       dispose
211     }
212   }
213
214   def dirty : Boolean = {
215     return reportSet.dirty
216   }
217
218   def save {
219     if (reportSet.file.isEmpty) {
220       val chooser = new FileChooser(Preferences.lastChosenDir())
221       val r = chooser.showSaveDialog(null)
222       if (r != FileChooser.Result.Approve) {
223         return
224       }
225
226       if (chooser.selectedFile.exists) {
227         val r = JOptionPane.showConfirmDialog(
228           peer,
229           "The chosen file or directory \"" + chooser.selectedFile.getName + "\" already exists.\n" +
230             "Do you want to overwrite it?",
231           "Confirmation",
232           JOptionPane.YES_NO_OPTION)
233
234         r match {
235           case JOptionPane.YES_OPTION =>
236           case JOptionPane.NO_OPTION  => return
237         }
238       }
239
240       Preferences.lastChosenDir() = chooser.selectedFile.getParentFile
241       reportSet.save(chooser.selectedFile)
242     }
243     else {
244       reportSet.save
245     }
246   }
247 }