1+ /*
2+ * Copyright 2018 Philipp Salvisberg <philipp.salvisberg@trivadis.com>
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+ package org.utplsql.sqldev
17+
18+ import java.awt.Component
19+ import java.awt.Dimension
20+ import java.awt.GridBagConstraints
21+ import java.awt.GridBagLayout
22+ import java.awt.Insets
23+ import java.awt.Rectangle
24+ import java.awt.Toolkit
25+ import java.awt.event.ActionEvent
26+ import java.awt.event.ActionListener
27+ import java.awt.event.FocusEvent
28+ import java.awt.event.FocusListener
29+ import java.awt.event.WindowEvent
30+ import javax.swing.BorderFactory
31+ import javax.swing.JButton
32+ import javax.swing.JFrame
33+ import javax.swing.JLabel
34+ import javax.swing.JPanel
35+ import javax.swing.JScrollPane
36+ import javax.swing.JTextArea
37+ import javax.swing.JTextField
38+ import javax.swing.ScrollPaneConstants
39+ import javax.swing.SwingUtilities
40+ import org.springframework.core.task.SimpleAsyncTaskExecutor
41+ import org.utplsql.sqldev.resources.UtplsqlResources
42+
43+ class CodeCoverageReporterWindow extends JFrame implements ActionListener , FocusListener {
44+
45+ var CodeCoverageReporter reporter
46+ var JButton runButton
47+ var JButton cancelButton
48+ var JPanel paneParams;
49+ var int paramPos = - 1 ;
50+ val pathsTextArea = new JTextArea ()
51+ val schemasTextField = new JTextField ()
52+ val includeObjectsTextArea = new JTextArea ()
53+ val excludeObjectsTextArea = new JTextArea ()
54+
55+ def static createAndShow (CodeCoverageReporter reporter ) {
56+ SwingUtilities . invokeLater(new Runnable () {
57+ override run() {
58+ CodeCoverageReporterWindow . createAndShowWithinEventThread(reporter);
59+ }
60+ });
61+ }
62+
63+ def private static createAndShowWithinEventThread (CodeCoverageReporter reporter ) {
64+ // create and layout the dialog
65+ val frame = new CodeCoverageReporterWindow (reporter)
66+ reporter. frame = frame
67+ frame. pack
68+ // center dialog
69+ val dim = Toolkit . getDefaultToolkit(). getScreenSize();
70+ frame. setLocation(dim. width / 2 - frame. getSize(). width / 2 , dim. height / 2 - frame. getSize(). height / 2 );
71+ frame. alwaysOnTop = true
72+ frame. visible = true
73+ }
74+
75+ new (CodeCoverageReporter reporter) {
76+ super (UtplsqlResources . getString(" WINDOW_CODE_COVERAGE_REPORT_LABEL" ))
77+ this . reporter = reporter
78+ val pane = this . getContentPane();
79+ pane. setLayout(new GridBagLayout ());
80+ val c = new GridBagConstraints ();
81+
82+ // parameters pane
83+ paneParams = new JPanel (new GridBagLayout ())
84+ pathsTextArea. editable = false
85+ pathsTextArea. enabled = false
86+ addParam(UtplsqlResources . getString(" WINDOW_PATHS_LABEL" ), ' ' ' «FOR path : reporter.pathList SEPARATOR ", "»«path»«ENDFOR»' ' ' , pathsTextArea)
87+ addParam(UtplsqlResources . getString(" WINDOW_SCHEMAS_LABEL" ), " " , schemasTextField);
88+ addParam(UtplsqlResources . getString(" WINDOW_INCLUDE_OBJECS_LABEL" ), ' ' ' «FOR i : reporter.includeObjectList SEPARATOR ", "»«i»«ENDFOR»' ' ' , includeObjectsTextArea);
89+ addParam(UtplsqlResources . getString(" WINDOW_EXCLUDE_OBJECS_LABEL" ), " " , excludeObjectsTextArea);
90+ val scrollPane = new JScrollPane (paneParams)
91+ scrollPane. verticalScrollBarPolicy = ScrollPaneConstants . VERTICAL_SCROLLBAR_AS_NEEDED
92+ scrollPane. horizontalScrollBarPolicy = ScrollPaneConstants . HORIZONTAL_SCROLLBAR_NEVER
93+ scrollPane. border = BorderFactory . createEmptyBorder;
94+ c. gridx = 0 ;
95+ c. gridy = 0 ;
96+ c. gridwidth = 2 ;
97+ c. insets = new Insets (10 , 10 , 0 , 10 ); // top, left, bottom, right
98+ c. anchor = GridBagConstraints . NORTH ;
99+ c. fill = GridBagConstraints . BOTH ;
100+ c. weightx = 1 ;
101+ c. weighty = 1 ;
102+ pane. add(scrollPane, c)
103+
104+ // Buttons pane
105+ val panelButtons = new JPanel (new GridBagLayout ())
106+ runButton = new JButton (UtplsqlResources . getString(" WINDOW_RUN_BUTTON" ))
107+ runButton. addActionListener(this );
108+ c. gridx = 0 ;
109+ c. gridy = 0 ;
110+ c. gridwidth = 1 ;
111+ c. insets = new Insets (0 , 0 , 0 , 0 ); // top, left, bottom, right
112+ c. fill = GridBagConstraints . NONE ;
113+ c. weightx = 0 ;
114+ c. weighty = 0 ;
115+ panelButtons. add(runButton, c);
116+ cancelButton = new JButton (UtplsqlResources . getString(" WINDOW_CANCEL_BUTTON" ));
117+ cancelButton. addActionListener(this );
118+ c. gridx = 1 ;
119+ c. insets = new Insets (0 , 10 , 0 , 0 ); // top, left, bottom, right
120+ c. fill = GridBagConstraints . NONE ;
121+ c. weightx = 0 ;
122+ c. weighty = 0 ;
123+ panelButtons. add(cancelButton, c);
124+ c. gridx = 1 ;
125+ c. gridy = 1 ;
126+ c. gridwidth = 1 ;
127+ c. insets = new Insets (30 , 10 , 10 , 10 ); // top, left, bottom, right
128+ c. anchor = GridBagConstraints . EAST
129+ c. fill = GridBagConstraints . NONE
130+ c. weightx = 0 ;
131+ c. weighty = 0 ;
132+ pane. add(panelButtons, c);
133+ pane. setPreferredSize(new Dimension (600 , 320 ));
134+ SwingUtilities . getRootPane(runButton). defaultButton = runButton
135+ }
136+
137+ private def addParam (String label , String text , Component component ) {
138+ paramPos++
139+ val c = new GridBagConstraints ();
140+ val paramLabel = new JLabel (label)
141+ c. gridx = 0
142+ c. gridy = paramPos
143+ c. gridwidth = 1
144+ c. insets = new Insets (10 , 10 , 0 , 0 ) // top, left, bottom, right
145+ c. anchor = GridBagConstraints . NORTHWEST
146+ c. fill = GridBagConstraints . HORIZONTAL
147+ c. weightx = 0
148+ c. weighty = 0
149+ paneParams. add(paramLabel, c);
150+ c. gridx = 1
151+ c. gridwidth = GridBagConstraints . REMAINDER
152+ c. anchor = GridBagConstraints . WEST
153+ c. fill = GridBagConstraints . BOTH
154+ c. insets = new Insets (10 , 10 , 0 , 10 ); // top, left, bottom, right
155+ c. weightx = 1
156+ if (component instanceof JTextField ) {
157+ component. text = text
158+ c. weighty = 0
159+ paneParams. add(component, c)
160+ } else if (component instanceof JTextArea ) {
161+ component. text = text
162+ component. lineWrap = true
163+ component. wrapStyleWord = true
164+ var scrollPane = new JScrollPane (component);
165+ scrollPane. viewport. preferredSize = new Dimension (200 , 50 )
166+ c. weighty = 1
167+ paneParams. add(scrollPane, c)
168+ }
169+ component. addFocusListener(this )
170+ }
171+
172+ def exit () {
173+ this . dispatchEvent(new WindowEvent (this , WindowEvent . WINDOW_CLOSING ));
174+ }
175+
176+ override actionPerformed (ActionEvent e ) {
177+ if (e. getSource == runButton) {
178+ reporter. schemas = schemasTextField. text
179+ reporter. includeObjects = includeObjectsTextArea. text
180+ reporter. excludeObjects = excludeObjectsTextArea. text
181+ schemasTextField. setEnabled(false )
182+ includeObjectsTextArea. setEnabled(false )
183+ excludeObjectsTextArea. setEnabled(false )
184+ runButton. setEnabled(false )
185+ reporter. runAsync
186+ } else if (e. getSource == cancelButton) {
187+ if (runButton. enabled) {
188+ // report is not yet started, just close the window
189+ exit
190+ } else {
191+ // report is being created...
192+ // frame will close as soon as the connection is technically aborted
193+ // database session is not cancelled. This is not a bug.
194+ // to cancel the session you have to kill it via "ALTER SYSTEM KILL SESSION".
195+ // However, the abort frees all resources on the client side.
196+ reporter. connection. abort(new SimpleAsyncTaskExecutor )
197+ }
198+ }
199+ }
200+
201+ override focusGained (FocusEvent e ) {
202+ if (paneParams. isAncestorOf(e. component)) {
203+ // make component at cursor position is visible
204+ val x = e. component. getLocationOnScreen. x - paneParams. getLocationOnScreen. x
205+ val y = e. component. getLocationOnScreen. y - paneParams. getLocationOnScreen. y
206+ val width = e. component. getBounds. width
207+ val height = e. component. getBounds. height
208+ val rect = new Rectangle (x, y, width, height)
209+ paneParams. scrollRectToVisible(rect)
210+ }
211+ }
212+
213+ override focusLost (FocusEvent e ) {
214+ // ignore
215+ }
216+
217+ }
0 commit comments