001: package net.sourceforge.tracelog.ui;
002:
003: import java.util.LinkedList;
004: import java.util.List;
005:
006: import net.sourceforge.tracelog.config.ConfigFile;
007: import net.sourceforge.tracelog.config.ConfigFileFactory;
008: import net.sourceforge.tracelog.config.LogGroup;
009: import net.sourceforge.tracelog.config.UserConfig;
010: import net.sourceforge.tracelog.listeners.GenericListener;
011: import net.sourceforge.tracelog.utils.Util;
012:
013: import org.eclipse.swt.SWT;
014: import org.eclipse.swt.events.MouseEvent;
015: import org.eclipse.swt.layout.GridLayout;
016: import org.eclipse.swt.widgets.Button;
017: import org.eclipse.swt.widgets.Composite;
018: import org.eclipse.swt.widgets.Event;
019: import org.eclipse.swt.widgets.Label;
020: import org.eclipse.swt.widgets.MessageBox;
021: import org.eclipse.swt.widgets.Table;
022: import org.eclipse.swt.widgets.TableColumn;
023: import org.eclipse.swt.widgets.TableItem;
024: import org.eclipse.swt.widgets.Text;
025:
026: public class ShellOptionLogGroup extends AbstractWidget {
027: // private static Logger log = Logger.getLogger(ShellOptionLogGroup.class);
028:
029: public static final int MAX_LOG_NAME_LENGTH = 15;
030: public static final int MAX_TABLE_ROW = 10;
031:
032: private static final int COLUMN_LOG_GROUP = 1;
033: private static final int COLUMN_NUMBER = 0;
034: private static final int COLUMN_TOTAL_LOG_FILES = 2;
035:
036: private static final String DEFAULT_VALUE = "[available slot]";
037:
038: private static final String[] TABLE_COLUMN_NAMES = { "#",
039: "Log Group", "Total Log Files" };
040:
041: private static final int[] TABLE_COLUMN_WIDTHS = { 30, 100, 450 };
042:
043: private Button cancelBtn;
044: private ConfigFile configFile;
045: private Button deleteBtn;
046: private Composite entryFieldsComposite;
047: private Text groupNameText;
048: private Composite logConfigComposite;
049: private List<LogGroup> logGroups;
050: private Button saveBtn;
051: private int selectedLogGroupIndex;
052:
053: private Table table;
054: private UserConfig userConfig;
055:
056: /**
057: * Package-access constructor.
058: */
059: ShellOptionLogGroup() {
060: super ();
061: this .table = null;
062: this .configFile = ConfigFileFactory.getInstance()
063: .getConfigFile();
064: this .userConfig = configFile.getUserConfig();
065: this .logGroups = userConfig.getLogGroups();
066: }
067:
068: public List<LogGroup> getLogGroups() {
069: return logGroups;
070: }
071:
072: /**
073: * Controller to display the log config dialog.
074: */
075: public void run() {
076:
077: logConfigComposite = new Composite(parentComposite, SWT.NONE);
078: logConfigComposite.setLayout(UIUtil.getDefaultGridLayout());
079: logConfigComposite.setLayoutData(UIUtil
080: .getGridDataFillHorizontal());
081:
082: widgetFactory.createLogConfigShellColorChooser(parentShell,
083: logConfigComposite, mediator);
084:
085: UIUtil.createTitle(logConfigComposite, "Log Groups");
086:
087: setupInstruction();
088: setupTable();
089: setupEntryFields();
090: setupButtons();
091:
092: parentComposite.layout();
093: }
094:
095: public void setLogGroup(List<LogGroup> logGroups) {
096: this .logGroups = logGroups;
097: }
098:
099: /**
100: * Deletes an entry field and updates the table content and the server log
101: * configuration.
102: */
103: private void deleteEntryField() {
104: // trying to delete an available entry
105: if (selectedLogGroupIndex < logGroups.size()) {
106:
107: if (logGroups.size() == 1) {
108: MessageBox mb = new MessageBox(parentShell, SWT.OK
109: | SWT.ICON_ERROR);
110: mb.setText("Log Groups Dialog");
111: mb
112: .setMessage("At least one log group must exist. Thus, you cannot delete this log group.");
113: mb.open();
114: return;
115: }
116:
117: LogGroup logGroup = logGroups.get(selectedLogGroupIndex);
118:
119: // total log file within this log group
120: int totalLogFiles = logGroup.getLogFiles().size();
121:
122: // this log group has at least one log file, ask user first before
123: // deleting it
124: if (totalLogFiles > 0) {
125: MessageBox mb = new MessageBox(parentShell,
126: SWT.ICON_QUESTION | SWT.YES | SWT.NO);
127: mb.setText("Log Groups Dialog");
128:
129: String msg = "Log group \""
130: + logGroup.getGroupName()
131: + "\" has at least one log file. "
132: + "If you delete this log group, its corresponding log file(s) will also be deleted. Do you really want to continue?";
133:
134: mb.setMessage(msg);
135:
136: if (mb.open() == SWT.YES) {
137: logGroups.remove(selectedLogGroupIndex);
138: notifyContentChange();
139: }
140: }
141: // log group that doesn't have log files, then just delete it
142: else {
143: logGroups.remove(selectedLogGroupIndex);
144: notifyContentChange();
145: }
146: } else {
147: hideEntryFields();
148: }
149: }
150:
151: private void displayEntryFields(String groupName) {
152: groupNameText.setText(groupName);
153:
154: entryFieldsComposite.setVisible(true);
155: saveBtn.setVisible(true);
156: cancelBtn.setVisible(true);
157: deleteBtn.setVisible(true);
158: }
159:
160: /**
161: * Displays the table content.
162: */
163: private void displayTableContent() {
164:
165: for (int i = 0; i < MAX_TABLE_ROW; ++i) {
166: LogGroup logGroup = (i < logGroups.size()) ? (LogGroup) logGroups
167: .get(i)
168: : new LogGroup();
169: logGroup.setGroupOrder(i);
170: setTableItem(i, logGroup);
171: }
172: }
173:
174: /**
175: * Hides the entry fields and the buttons.
176: */
177: private void hideEntryFields() {
178: entryFieldsComposite.setVisible(false);
179:
180: if (saveBtn != null && !saveBtn.isDisposed()) {
181: saveBtn.setVisible(false);
182: }
183:
184: if (cancelBtn != null && !cancelBtn.isDisposed()) {
185: cancelBtn.setVisible(false);
186: }
187:
188: if (deleteBtn != null && !deleteBtn.isDisposed()) {
189: deleteBtn.setVisible(false);
190: }
191: }
192:
193: private void notifyContentChange() {
194: configFile.saveUserConfig(userConfig);
195: mediator.handleEvent(ActionMediator.EVENT_REDRAW_LOG_VIEWERS);
196: table.clearAll();
197: displayTableContent();
198: hideEntryFields();
199: }
200:
201: /**
202: * Performs validation on the entry fields before saving the configuration
203: * permanently.
204: */
205: private void saveConfig() {
206: String msg = "";
207:
208: List<String> existingGroupNames = new LinkedList<String>();
209:
210: // get all the existing group names excluding the selected entry
211: for (int i = 0; i < logGroups.size(); ++i) {
212: if (i != selectedLogGroupIndex) {
213: existingGroupNames.add(logGroups.get(i).getGroupName());
214: }
215: }
216:
217: String groupName = groupNameText.getText();
218:
219: // empty field
220: if (Util.isEmpty(groupName)) {
221: msg += Util.LINE_BREAK + "- Log group name must exist.";
222: }
223: // log name has invalid characters
224: else if (!groupName.matches("[A-Za-z0-9_ ]*")) {
225: msg += Util.LINE_BREAK
226: + "- Log group name has invalid character(s). Please use only alphanumeric, underscore and space.";
227: }
228: // log name already exists
229: else if (existingGroupNames.contains(groupName)) {
230: msg += Util.LINE_BREAK
231: + "- Log group name already exists. Make sure all log group names are unique.";
232: }
233: // no errors
234: else {
235: LogGroup logGroup = null;
236: int newTableItemIndex = 0;
237:
238: if (selectedLogGroupIndex < logGroups.size()) {
239: newTableItemIndex = selectedLogGroupIndex;
240: logGroup = logGroups.get(selectedLogGroupIndex);
241: logGroup.setGroupName(groupName);
242: } else {
243: newTableItemIndex = logGroups.size();
244: logGroup = new LogGroup();
245: logGroup.setGroupOrder(newTableItemIndex + 1);
246: logGroup.setGroupName(groupName);
247: logGroups.add(logGroup);
248: }
249:
250: notifyContentChange();
251:
252: return;
253: }
254:
255: // will reach here if there is error
256: MessageBox mb = new MessageBox(parentShell, SWT.OK
257: | SWT.ICON_ERROR);
258: mb.setText("Log Files Dialog");
259: mb.setMessage("Please fix the following error(s):"
260: + Util.LINE_BREAK + msg);
261: mb.open();
262: }
263:
264: private void setTableItem(int tableItemIndex, LogGroup logGroup) {
265: TableItem tableItem = null;
266:
267: String groupName = logGroup.getGroupName();
268: int totalLogFiles = logGroup.getLogFiles().size();
269:
270: if (groupName.isEmpty()) {
271: groupName = DEFAULT_VALUE;
272: totalLogFiles = 0;
273: }
274:
275: if (tableItemIndex < table.getItemCount()) {
276: tableItem = table.getItem(tableItemIndex);
277: } else {
278: tableItem = new TableItem(table, SWT.NONE);
279: }
280:
281: tableItem.setText(COLUMN_NUMBER, String
282: .valueOf(tableItemIndex + 1)
283: + ".");
284: tableItem.setText(COLUMN_LOG_GROUP, groupName);
285: tableItem.setText(COLUMN_TOTAL_LOG_FILES, String
286: .valueOf(totalLogFiles));
287:
288: tableItem.setData(logGroup);
289: }
290:
291: /**
292: * Sets up action buttons: save, cancel, delete and close.
293: */
294: private void setupButtons() {
295: Composite c = new Composite(logConfigComposite, SWT.NONE);
296: c.setLayout(new GridLayout(5, true));
297: c.setLayoutData(UIUtil.getGridDataFillHorizontal());
298:
299: Label label = new Label(c, SWT.NONE);
300: label.setLayoutData(UIUtil.getGridDataFillHorizontalSpan(2));
301:
302: saveBtn = new Button(c, SWT.PUSH);
303: saveBtn.setText("Save");
304: saveBtn.setVisible(false);
305: saveBtn.setLayoutData(UIUtil.getGridDataFillHorizontal());
306:
307: saveBtn.addMouseListener(new GenericListener() {
308: public void mouseUp(MouseEvent e) {
309: saveConfig();
310: }
311: });
312:
313: cancelBtn = new Button(c, SWT.PUSH);
314: cancelBtn.setText("Cancel");
315: cancelBtn.setVisible(false);
316: cancelBtn.setLayoutData(UIUtil.getGridDataFillHorizontal());
317:
318: cancelBtn.addMouseListener(new GenericListener() {
319: public void mouseUp(MouseEvent e) {
320: hideEntryFields();
321: }
322: });
323:
324: deleteBtn = new Button(c, SWT.PUSH);
325: deleteBtn.setText("Delete");
326: deleteBtn.setVisible(false);
327: deleteBtn.setLayoutData(UIUtil.getGridDataFillHorizontal());
328:
329: deleteBtn.addMouseListener(new GenericListener() {
330: public void mouseUp(MouseEvent e) {
331: deleteEntryField();
332: }
333: });
334: }
335:
336: /**
337: * Sets up the entry fields for configuring the logs. These entry fields are
338: * by default hidden until a log is selected from the table.
339: */
340: private void setupEntryFields() {
341: entryFieldsComposite = new Composite(logConfigComposite,
342: SWT.NONE);
343: GridLayout gridLayout = new GridLayout(5, true);
344: entryFieldsComposite.setLayout(gridLayout);
345: entryFieldsComposite.setLayoutData(UIUtil
346: .getGridDataFillHorizontal());
347:
348: // log name
349: setupLeftEntryField(entryFieldsComposite, "Log Name");
350:
351: groupNameText = new Text(entryFieldsComposite, SWT.BORDER);
352: groupNameText.setBackground(display
353: .getSystemColor(SWT.COLOR_WHITE));
354: groupNameText.setLayoutData(UIUtil.getGridDataFillHorizontal());
355: groupNameText.setTextLimit(MAX_LOG_NAME_LENGTH);
356:
357: hideEntryFields();
358: }
359:
360: /**
361: * Displays the instruction label.
362: */
363: private void setupInstruction() {
364: Label label = new Label(logConfigComposite, SWT.WRAP);
365: label.setLayoutData(UIUtil.getGridDataFillHorizontal());
366: String msg = "The log group enables you to logically group the log files together. "
367: + "For example, each log group can represent a server environment that contains a set of log files. "
368: + "This feature also enables you to easily control which log group you wish to monitor/unmonitor at present time. "
369: + "For example, if you have several log groups, you only probably want to enable real-time monitoring on one log group "
370: + "while keeping the rest of the log groups disabled until you absolutely need to run them. "
371: + Util.LINE_BREAK
372: + Util.LINE_BREAK
373: + "At least one log group MUST exist and you can create up to "
374: + MAX_TABLE_ROW
375: + " log groups here. "
376: + "In order for the log group tabs to appear in "
377: + projectProperties.getApplicationTitle()
378: + ", you need to setup at least two log groups. "
379: + Util.LINE_BREAK + Util.LINE_BREAK;
380:
381: label.setText(msg);
382: }
383:
384: /**
385: * Displays a right aligned label.
386: *
387: * @param composite
388: * Composite parent.
389: * @param value
390: * Label value.
391: */
392: private void setupLeftEntryField(Composite composite, String value) {
393: Label label = new Label(composite, SWT.NONE);
394: label.setLayoutData(UIUtil.getGridDataFillHorizontal());
395: label.setAlignment(SWT.RIGHT);
396: label.setText(value + " : ");
397: }
398:
399: /**
400: * Sets up the contents in the table.
401: */
402: private void setupTable() {
403: table = new Table(logConfigComposite, SWT.BORDER
404: | SWT.FULL_SELECTION);
405: table.setLayoutData(UIUtil.getGridDataFillBoth());
406: table.setLinesVisible(true);
407: table.setHeaderVisible(true);
408: table.setCursor(UIUtil.getCursorHand());
409: table.addListener(SWT.Selection, new GenericListener() {
410: public void handleEvent(Event event) {
411: TableItem tableItem = (TableItem) event.item;
412: LogGroup logGroup = (LogGroup) tableItem.getData();
413:
414: selectedLogGroupIndex = logGroup.getGroupOrder();
415: displayEntryFields(logGroup.getGroupName());
416:
417: }
418: });
419:
420: for (int i = 0; i < TABLE_COLUMN_NAMES.length; ++i) {
421: final TableColumn column = new TableColumn(table, SWT.LEFT);
422: column.setText(TABLE_COLUMN_NAMES[i]);
423: column.setWidth(TABLE_COLUMN_WIDTHS[i]);
424: }
425:
426: displayTableContent();
427: }
428: }
|