javablogspot

Just another WordPress.com weblog

screw all gui builders

Posted by damuchinni on February 14, 2009

Are you making your GUI with a builder? Do you like the generated code you get? I hate it. Even though I like the idea of building GUI with visual means (WYSIWYG), I can’t stand the mess that code generators produce. In addition to that, there are more serious downsides: * You don’t know how exactly the generated code works. You don’t need to. You start not to care and GUI application development becomes a process of drawing and adding simple event handlers here and there. * Most GUI builders force you to use single class for single window, so generated classes tend to have thousands of lines of code. * Most GUI builders don’t want you to modify the generated code. And if you do, they either break or rewrite your code. * GUI builders force you to use an IDE, mostly one you started coding with. So if you start with NetBeans, you most likely be forced to stay with it for the whole project. * The generated code is far from being optimal. It’s not resize-friendly, not dynamic enough, it has many hard-coded values, refactoring is most likely impossible, because builder would not allow that. So, why are you using GUI builders? Is it because you’re doing GUI apps during your day job, you need fast results and you don’t want to learn more than you have to? Or you just have no choice? That’s reasonable, but when you have a choice, consider learning how Swing or SWT works, spend some time reading the API docs and examining the code – it’s amazing how fast and dynamic your GUI building process can get when you finally get a clear understanding HOW to use all the widgets and layouts. Let me show you. Here’s a window from Hawkscope app that I’m making in my spare time. It was generated with Jigloo GUI builder in Eclipse. First let’s see how it looks: The code (all comments removed): view plainprint? 1. package com.varaneckas.hawkscope.gui; 2. 3. import org.eclipse.swt.SWT; 4. import org.eclipse.swt.events.MouseAdapter; 5. import org.eclipse.swt.events.MouseEvent; 6. import org.eclipse.swt.events.PaintEvent; 7. import org.eclipse.swt.events.PaintListener; 8. import org.eclipse.swt.events.SelectionAdapter; 9. import org.eclipse.swt.events.SelectionEvent; 10. import org.eclipse.swt.graphics.Color; 11. import org.eclipse.swt.graphics.Cursor; 12. import org.eclipse.swt.layout.FormAttachment; 13. import org.eclipse.swt.layout.FormData; 14. import org.eclipse.swt.layout.FormLayout; 15. import org.eclipse.swt.program.Program; 16. import org.eclipse.swt.widgets.Button; 17. import org.eclipse.swt.widgets.Canvas; 18. import org.eclipse.swt.widgets.Display; 19. import org.eclipse.swt.widgets.Label; 20. import org.eclipse.swt.widgets.Shell; 21. import org.eclipse.swt.widgets.Text; 22. 23. import com.cloudgarden.resource.SWTResourceManager; 24. import com.varaneckas.hawkscope.Version; 25. import com.varaneckas.hawkscope.cfg.ConfigurationFactory; 26. import com.varaneckas.hawkscope.util.IOUtils; 27. import com.varaneckas.hawkscope.util.IconFactory; 28. import com.varaneckas.hawkscope.util.OSUtils; 29. 30. public class AboutWindow extends org.eclipse.swt.widgets.Dialog { 31. 32. private Shell dialogShell; 33. private Canvas logoCanvas; 34. private Label appNameLabel; 35. private Label appSloganLabel; 36. private Label appVersion; 37. private Label appHomepageValue; 38. private Button copyReportButton; 39. private Button closeButton; 40. private Label environmentLabel; 41. private Text environmentTextArea; 42. private Label appHomepageLabel; 43. private Label appReleasedValue; 44. private Label appReleasedLabel; 45. private Label appVersionValue; 46. 47. public AboutWindow(final Shell parent, final int style) { 48. super(parent, style); 49. } 50. 51. public synchronized void open() { 52. if (dialogShell != null && !dialogShell.isDisposed()) { 53. dialogShell.setVisible(true); 54. dialogShell.forceFocus(); 55. return; 56. } 57. final Shell parent = getParent(); 58. dialogShell = new Shell(parent, SWT.DIALOG_TRIM 59. | SWT.APPLICATION_MODAL); 60. { 61. SWTResourceManager.registerResourceUser(dialogShell); 62. } 63. dialogShell.setImage(IconFactory.getInstance() 64. .getUncachedIcon(“hawkscope16.png”)); 65. dialogShell.setText(“About”); 66. 67. dialogShell.setLayout(new FormLayout()); 68. dialogShell.layout(); 69. dialogShell.pack(); 70. dialogShell.setSize(516, 322); 71. { 72. copyReportButton = new Button(dialogShell, SWT.PUSH | SWT.CENTER); 73. FormData copyReportButtonLData = new FormData(); 74. copyReportButtonLData.width = 125; 75. copyReportButtonLData.height = 29; 76. copyReportButtonLData.left = new FormAttachment(0, 1000, 314); 77. copyReportButtonLData.top = new FormAttachment(0, 1000, 252); 78. copyReportButton.setLayoutData(copyReportButtonLData); 79. copyReportButton.addSelectionListener(new SelectionAdapter() { 80. @Override 81. public void widgetSelected(SelectionEvent event) { 82. IOUtils.copyToClipboard(Version.getEnvironmentReport()); 83. } 84. }); 85. copyReportButton.setText(“Co&py to Clipboard”); 86. OSUtils.adjustButton(copyReportButton); 87. } 88. { 89. closeButton = new Button(dialogShell, SWT.PUSH | SWT.CENTER); 90. FormData closeButtonLData = new FormData(); 91. closeButtonLData.width = 47; 92. closeButtonLData.height = 29; 93. closeButtonLData.left = new FormAttachment(0, 1000, 451); 94. closeButtonLData.top = new FormAttachment(0, 1000, 252); 95. closeButton.setLayoutData(closeButtonLData); 96. closeButton.addSelectionListener(new SelectionAdapter() { 97. @Override 98. public void widgetSelected(SelectionEvent event) { 99. dialogShell.dispose(); 100. } 101. }); 102. closeButton.setText(“&Close”); 103. OSUtils.adjustButton(closeButton); 104. } 105. { 106. environmentLabel = new Label(dialogShell, SWT.NONE); 107. FormData environmentLabelLData = new FormData(); 108. environmentLabelLData.width = 486; 109. environmentLabelLData.height = 17; 110. environmentLabelLData.left = new FormAttachment(0, 1000, 12); 111. environmentLabelLData.top = new FormAttachment(0, 1000, 127); 112. environmentLabel.setLayoutData(environmentLabelLData); 113. environmentLabel.setText(“Environment”); 114. environmentLabel.setFont(SWTResourceManager.getFont(“Sans”, 10, 1)); 115. } 116. { 117. environmentTextArea = new Text(dialogShell, SWT.MULTI | SWT.WRAP 118. | SWT.V_SCROLL | SWT.BORDER); 119. FormData environmentTextAreaLData = new FormData(); 120. environmentTextAreaLData.width = 468; 121. environmentTextAreaLData.height = 90; 122. environmentTextAreaLData.left = new FormAttachment(0, 1000, 12); 123. environmentTextAreaLData.top = new FormAttachment(0, 1000, 150); 124. environmentTextArea.setLayoutData(environmentTextAreaLData); 125. environmentTextArea.setText(Version.getSystemProperties()); 126. environmentTextArea.setEditable(false); 127. } 128. { 129. appHomepageValue = new Label(dialogShell, SWT.NONE); 130. appHomepageValue.addMouseListener(new MouseAdapter() { 131. @Override 132. public void mouseUp(MouseEvent event) { 133. Program.launch(Version.HOMEPAGE); 134. } 135. }); 136. appHomepageValue.setCursor(new Cursor(dialogShell.getDisplay(), 137. SWT.CURSOR_HAND)); 138. appHomepageValue.setForeground( 139. new Color(dialogShell.getDisplay(), 0, 0, 255)); 140. FormData appHomepageValueLData = new FormData(); 141. appHomepageValueLData.width = 242; 142. appHomepageValueLData.height = 17; 143. appHomepageValueLData.left = new FormAttachment(0, 1000, 256); 144. appHomepageValueLData.top = new FormAttachment(0, 1000, 104); 145. appHomepageValue.setLayoutData(appHomepageValueLData); 146. appHomepageValue.setToolTipText(“Click to open in browser”); 147. appHomepageValue.setText(Version.HOMEPAGE); 148. } 149. { 150. appHomepageLabel = new Label(dialogShell, SWT.NONE); 151. FormData appHomepageLabelLData = new FormData(); 152. appHomepageLabelLData.width = 94; 153. appHomepageLabelLData.height = 17; 154. appHomepageLabelLData.left = new FormAttachment(0, 1000, 156); 155. appHomepageLabelLData.top = new FormAttachment(0, 1000, 104); 156. appHomepageLabel.setLayoutData(appHomepageLabelLData); 157. appHomepageLabel.setText(“Homepage:”); 158. appHomepageLabel.setFont(SWTResourceManager.getFont(“Sans”, 10, 1)); 159. } 160. { 161. appReleasedValue = new Label(dialogShell, SWT.NONE); 162. FormData appReleasedValueLData = new FormData(); 163. appReleasedValueLData.width = 242; 164. appReleasedValueLData.height = 17; 165. appReleasedValueLData.left = new FormAttachment(0, 1000, 256); 166. appReleasedValueLData.top = new FormAttachment(0, 1000, 81); 167. appReleasedValue.setLayoutData(appReleasedValueLData); 168. appReleasedValue.setText(Version.VERSION_DATE); 169. } 170. { 171. appReleasedLabel = new Label(dialogShell, SWT.NONE); 172. FormData appReleasedLabelLData = new FormData(); 173. appReleasedLabelLData.width = 77; 174. appReleasedLabelLData.height = 17; 175. appReleasedLabelLData.left = new FormAttachment(0, 1000, 156); 176. appReleasedLabelLData.top = new FormAttachment(0, 1000, 81); 177. appReleasedLabel.setLayoutData(appReleasedLabelLData); 178. appReleasedLabel.setText(“Released:”); 179. appReleasedLabel.setFont(SWTResourceManager.getFont(“Sans”, 10, 1)); 180. } 181. { 182. appVersionValue = new Label(dialogShell, SWT.NONE); 183. FormData appVersionValueLData = new FormData(); 184. appVersionValueLData.width = 242; 185. appVersionValueLData.height = 17; 186. appVersionValueLData.left = new FormAttachment(0, 1000, 256); 187. appVersionValueLData.top = new FormAttachment(0, 1000, 58); 188. appVersionValue.setLayoutData(appVersionValueLData); 189. if (Version.isUpdateAvailable() == null) { 190. appVersionValue.setText(Version.VERSION_NUMBER); 191. if (ConfigurationFactory.getConfigurationFactory() 192. .getConfiguration().checkForUpdates()) { 193. appVersionValue.setToolTipText(“Could not get version information.”); 194. } 195. } else { 196. if (Version.isUpdateAvailable()) { 197. appVersionValue.setForeground(new Color(dialogShell 198. .getDisplay(), 255, 0, 0)); 199. appVersionValue.setText(Version.VERSION_NUMBER 200. + ” (Update Available!)”); 201. appVersionValue.setToolTipText(“Click to go to update ” + 202. “download page”); 203. appVersionValue.setCursor(new Cursor(dialogShell 204. .getDisplay(), SWT.CURSOR_HAND)); 205. appVersionValue.addMouseListener(new MouseAdapter() { 206. @Override 207. public void mouseUp(MouseEvent event) { 208. Program.launch(Version.DOWNLOAD_URL); 209. dialogShell.dispose(); 210. } 211. }); 212. } else { 213. appVersionValue.setText(Version.VERSION_NUMBER); 214. appVersionValue.setToolTipText(“Latest available version!”); 215. appVersionValue.setForeground(new Color(dialogShell 216. .getDisplay(), 0, 128, 0)); 217. } 218. } 219. } 220. { 221. appVersion = new Label(dialogShell, SWT.NONE); 222. FormData appVersionLData = new FormData(); 223. appVersionLData.width = 77; 224. appVersionLData.height = 17; 225. appVersionLData.left = new FormAttachment(0, 1000, 156); 226. appVersionLData.top = new FormAttachment(0, 1000, 58); 227. appVersion.setLayoutData(appVersionLData); 228. appVersion.setText(“Version:”); 229. appVersion.setFont(SWTResourceManager.getFont(“Sans”, 10, 1)); 230. } 231. { 232. appSloganLabel = new Label(dialogShell, SWT.WRAP); 233. FormData appSloganLabelLData = new FormData(); 234. appSloganLabelLData.width = 342; 235. appSloganLabelLData.height = 17; 236. appSloganLabelLData.left = new FormAttachment(0, 1000, 156); 237. appSloganLabelLData.top = new FormAttachment(0, 1000, 35); 238. appSloganLabel.setLayoutData(appSloganLabelLData); 239. appSloganLabel.setText(Version.APP_SLOGAN); 240. } 241. { 242. appNameLabel = new Label(dialogShell, SWT.NONE); 243. FormData appNameLabelLData = new FormData(); 244. appNameLabelLData.width = 342; 245. appNameLabelLData.height = 17; 246. appNameLabelLData.left = new FormAttachment(0, 1000, 156); 247. appNameLabelLData.top = new FormAttachment(0, 1000, 12); 248. appNameLabel.setLayoutData(appNameLabelLData); 249. appNameLabel.setText(“Hawkscope”); 250. appNameLabel.setFont(SWTResourceManager.getFont(“Sans”, 10, 1)); 251. } 252. { 253. final FormData logoCanvasLData = new FormData(); 254. logoCanvasLData.width = 114; 255. logoCanvasLData.height = 109; 256. logoCanvasLData.left = new FormAttachment(0, 1000, 12); 257. logoCanvasLData.top = new FormAttachment(0, 1000, 12); 258. logoCanvas = new Canvas(dialogShell, SWT.RESIZE); 259. logoCanvas.addPaintListener(new PaintListener() { 260. public void paintControl(PaintEvent e) { 261. e.gc.drawImage(IconFactory.getInstance() 262. .getUncachedIcon(“hawkscope128.png”), 0, 0, 128, 263. 128, 0, 0, 114, 109); 264. } 265. }); 266. logoCanvas.addMouseListener(new MouseAdapter() { 267. @Override 268. public void mouseUp(MouseEvent event) { 269. Program.launch(Version.HOMEPAGE); 270. } 271. }); 272. logoCanvas.setCursor(new Cursor(dialogShell.getDisplay(), 273. SWT.CURSOR_HAND)); 274. logoCanvas.setToolTipText(“Click to visit Homepage”); 275. logoCanvas.setLayoutData(logoCanvasLData); 276. } 277. dialogShell.setLocation(getParent().toDisplay(100, 100)); 278. dialogShell.open(); 279. Display display = dialogShell.getDisplay(); 280. while (!dialogShell.isDisposed()) { 281. if (!display.readAndDispatch()) 282. display.sleep(); 283. } 284. } 285. 286. } package com.varaneckas.hawkscope.gui; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Cursor; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.program.Program; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import com.cloudgarden.resource.SWTResourceManager; import com.varaneckas.hawkscope.Version; import com.varaneckas.hawkscope.cfg.ConfigurationFactory; import com.varaneckas.hawkscope.util.IOUtils; import com.varaneckas.hawkscope.util.IconFactory; import com.varaneckas.hawkscope.util.OSUtils; public class AboutWindow extends org.eclipse.swt.widgets.Dialog { private Shell dialogShell; private Canvas logoCanvas; private Label appNameLabel; private Label appSloganLabel; private Label appVersion; private Label appHomepageValue; private Button copyReportButton; private Button closeButton; private Label environmentLabel; private Text environmentTextArea; private Label appHomepageLabel; private Label appReleasedValue; private Label appReleasedLabel; private Label appVersionValue; public AboutWindow(final Shell parent, final int style) { super(parent, style); } public synchronized void open() { if (dialogShell != null && !dialogShell.isDisposed()) { dialogShell.setVisible(true); dialogShell.forceFocus(); return; } final Shell parent = getParent(); dialogShell = new Shell(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL); { SWTResourceManager.registerResourceUser(dialogShell); } dialogShell.setImage(IconFactory.getInstance() .getUncachedIcon(“hawkscope16.png”)); dialogShell.setText(“About”); dialogShell.setLayout(new FormLayout()); dialogShell.layout(); dialogShell.pack(); dialogShell.setSize(516, 322); { copyReportButton = new Button(dialogShell, SWT.PUSH | SWT.CENTER); FormData copyReportButtonLData = new FormData(); copyReportButtonLData.width = 125; copyReportButtonLData.height = 29; copyReportButtonLData.left = new FormAttachment(0, 1000, 314); copyReportButtonLData.top = new FormAttachment(0, 1000, 252); copyReportButton.setLayoutData(copyReportButtonLData); copyReportButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { IOUtils.copyToClipboard(Version.getEnvironmentReport()); } }); copyReportButton.setText(“Co&py to Clipboard”); OSUtils.adjustButton(copyReportButton); } { closeButton = new Button(dialogShell, SWT.PUSH | SWT.CENTER); FormData closeButtonLData = new FormData(); closeButtonLData.width = 47; closeButtonLData.height = 29; closeButtonLData.left = new FormAttachment(0, 1000, 451); closeButtonLData.top = new FormAttachment(0, 1000, 252); closeButton.setLayoutData(closeButtonLData); closeButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { dialogShell.dispose(); } }); closeButton.setText(“&Close”); OSUtils.adjustButton(closeButton); } { environmentLabel = new Label(dialogShell, SWT.NONE); FormData environmentLabelLData = new FormData(); environmentLabelLData.width = 486; environmentLabelLData.height = 17; environmentLabelLData.left = new FormAttachment(0, 1000, 12); environmentLabelLData.top = new FormAttachment(0, 1000, 127); environmentLabel.setLayoutData(environmentLabelLData); environmentLabel.setText(“Environment”); environmentLabel.setFont(SWTResourceManager.getFont(“Sans”, 10, 1)); } { environmentTextArea = new Text(dialogShell, SWT.MULTI | SWT.WRAP | SWT.V_SCROLL | SWT.BORDER); FormData environmentTextAreaLData = new FormData(); environmentTextAreaLData.width = 468; environmentTextAreaLData.height = 90; environmentTextAreaLData.left = new FormAttachment(0, 1000, 12); environmentTextAreaLData.top = new FormAttachment(0, 1000, 150); environmentTextArea.setLayoutData(environmentTextAreaLData); environmentTextArea.setText(Version.getSystemProperties()); environmentTextArea.setEditable(false); } { appHomepageValue = new Label(dialogShell, SWT.NONE); appHomepageValue.addMouseListener(new MouseAdapter() { @Override public void mouseUp(MouseEvent event) { Program.launch(Version.HOMEPAGE); } }); appHomepageValue.setCursor(new Cursor(dialogShell.getDisplay(), SWT.CURSOR_HAND)); appHomepageValue.setForeground( new Color(dialogShell.getDisplay(), 0, 0, 255)); FormData appHomepageValueLData = new FormData(); appHomepageValueLData.width = 242; appHomepageValueLData.height = 17; appHomepageValueLData.left = new FormAttachment(0, 1000, 256); appHomepageValueLData.top = new FormAttachment(0, 1000, 104); appHomepageValue.setLayoutData(appHomepageValueLData); appHomepageValue.setToolTipText(“Click to open in browser”); appHomepageValue.setText(Version.HOMEPAGE); } { appHomepageLabel = new Label(dialogShell, SWT.NONE); FormData appHomepageLabelLData = new FormData(); appHomepageLabelLData.width = 94; appHomepageLabelLData.height = 17; appHomepageLabelLData.left = new FormAttachment(0, 1000, 156); appHomepageLabelLData.top = new FormAttachment(0, 1000, 104); appHomepageLabel.setLayoutData(appHomepageLabelLData); appHomepageLabel.setText(“Homepage:”); appHomepageLabel.setFont(SWTResourceManager.getFont(“Sans”, 10, 1)); } { appReleasedValue = new Label(dialogShell, SWT.NONE); FormData appReleasedValueLData = new FormData(); appReleasedValueLData.width = 242; appReleasedValueLData.height = 17; appReleasedValueLData.left = new FormAttachment(0, 1000, 256); appReleasedValueLData.top = new FormAttachment(0, 1000, 81); appReleasedValue.setLayoutData(appReleasedValueLData); appReleasedValue.setText(Version.VERSION_DATE); } { appReleasedLabel = new Label(dialogShell, SWT.NONE); FormData appReleasedLabelLData = new FormData(); appReleasedLabelLData.width = 77; appReleasedLabelLData.height = 17; appReleasedLabelLData.left = new FormAttachment(0, 1000, 156); appReleasedLabelLData.top = new FormAttachment(0, 1000, 81); appReleasedLabel.setLayoutData(appReleasedLabelLData); appReleasedLabel.setText(“Released:”); appReleasedLabel.setFont(SWTResourceManager.getFont(“Sans”, 10, 1)); } { appVersionValue = new Label(dialogShell, SWT.NONE); FormData appVersionValueLData = new FormData(); appVersionValueLData.width = 242; appVersionValueLData.height = 17; appVersionValueLData.left = new FormAttachment(0, 1000, 256); appVersionValueLData.top = new FormAttachment(0, 1000, 58); appVersionValue.setLayoutData(appVersionValueLData); if (Version.isUpdateAvailable() == null) { appVersionValue.setText(Version.VERSION_NUMBER); if (ConfigurationFactory.getConfigurationFactory() .getConfiguration().checkForUpdates()) { appVersionValue.setToolTipText(“Could not get version information.”); } } else { if (Version.isUpdateAvailable()) { appVersionValue.setForeground(new Color(dialogShell .getDisplay(), 255, 0, 0)); appVersionValue.setText(Version.VERSION_NUMBER + ” (Update Available!)”); appVersionValue.setToolTipText(“Click to go to update ” + “download page”); appVersionValue.setCursor(new Cursor(dialogShell .getDisplay(), SWT.CURSOR_HAND)); appVersionValue.addMouseListener(new MouseAdapter() { @Override public void mouseUp(MouseEvent event) { Program.launch(Version.DOWNLOAD_URL); dialogShell.dispose(); } }); } else { appVersionValue.setText(Version.VERSION_NUMBER); appVersionValue.setToolTipText(“Latest available version!”); appVersionValue.setForeground(new Color(dialogShell .getDisplay(), 0, 128, 0)); } } } { appVersion = new Label(dialogShell, SWT.NONE); FormData appVersionLData = new FormData(); appVersionLData.width = 77; appVersionLData.height = 17; appVersionLData.left = new FormAttachment(0, 1000, 156); appVersionLData.top = new FormAttachment(0, 1000, 58); appVersion.setLayoutData(appVersionLData); appVersion.setText(“Version:”); appVersion.setFont(SWTResourceManager.getFont(“Sans”, 10, 1)); } { appSloganLabel = new Label(dialogShell, SWT.WRAP); FormData appSloganLabelLData = new FormData(); appSloganLabelLData.width = 342; appSloganLabelLData.height = 17; appSloganLabelLData.left = new FormAttachment(0, 1000, 156); appSloganLabelLData.top = new FormAttachment(0, 1000, 35); appSloganLabel.setLayoutData(appSloganLabelLData); appSloganLabel.setText(Version.APP_SLOGAN); } { appNameLabel = new Label(dialogShell, SWT.NONE); FormData appNameLabelLData = new FormData(); appNameLabelLData.width = 342; appNameLabelLData.height = 17; appNameLabelLData.left = new FormAttachment(0, 1000, 156); appNameLabelLData.top = new FormAttachment(0, 1000, 12); appNameLabel.setLayoutData(appNameLabelLData); appNameLabel.setText(“Hawkscope”); appNameLabel.setFont(SWTResourceManager.getFont(“Sans”, 10, 1)); } { final FormData logoCanvasLData = new FormData(); logoCanvasLData.width = 114; logoCanvasLData.height = 109; logoCanvasLData.left = new FormAttachment(0, 1000, 12); logoCanvasLData.top = new FormAttachment(0, 1000, 12); logoCanvas = new Canvas(dialogShell, SWT.RESIZE); logoCanvas.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { e.gc.drawImage(IconFactory.getInstance() .getUncachedIcon(“hawkscope128.png”), 0, 0, 128, 128, 0, 0, 114, 109); } }); logoCanvas.addMouseListener(new MouseAdapter() { @Override public void mouseUp(MouseEvent event) { Program.launch(Version.HOMEPAGE); } }); logoCanvas.setCursor(new Cursor(dialogShell.getDisplay(), SWT.CURSOR_HAND)); logoCanvas.setToolTipText(“Click to visit Homepage”); logoCanvas.setLayoutData(logoCanvasLData); } dialogShell.setLocation(getParent().toDisplay(100, 100)); dialogShell.open(); Display display = dialogShell.getDisplay(); while (!dialogShell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } } } Now, a hand-rewritten version with no GUI builder: The code: view plainprint? 1. package com.varaneckas.hawkscope.gui; 2. 3. import org.eclipse.swt.SWT; 4. import org.eclipse.swt.events.MouseAdapter; 5. import org.eclipse.swt.events.MouseEvent; 6. import org.eclipse.swt.events.PaintEvent; 7. import org.eclipse.swt.events.PaintListener; 8. import org.eclipse.swt.events.SelectionAdapter; 9. import org.eclipse.swt.events.SelectionEvent; 10. import org.eclipse.swt.graphics.Color; 11. import org.eclipse.swt.graphics.Cursor; 12. import org.eclipse.swt.graphics.Font; 13. import org.eclipse.swt.graphics.FontData; 14. import org.eclipse.swt.layout.FormAttachment; 15. import org.eclipse.swt.layout.FormData; 16. import org.eclipse.swt.layout.FormLayout; 17. import org.eclipse.swt.program.Program; 18. import org.eclipse.swt.widgets.Button; 19. import org.eclipse.swt.widgets.Canvas; 20. import org.eclipse.swt.widgets.Control; 21. import org.eclipse.swt.widgets.Label; 22. import org.eclipse.swt.widgets.Shell; 23. import org.eclipse.swt.widgets.Text; 24. 25. import com.varaneckas.hawkscope.Version; 26. import com.varaneckas.hawkscope.cfg.ConfigurationFactory; 27. import com.varaneckas.hawkscope.tray.TrayManager; 28. import com.varaneckas.hawkscope.util.IOUtils; 29. import com.varaneckas.hawkscope.util.IconFactory; 30. 31. public class AboutShell { 32. 33. private Shell shell; 34. private FormData layout; 35. private Font bold; 36. private Color red; 37. private Color green; 38. private Color blue; 39. private Cursor hand; 40. private Canvas logo; 41. private Label labelAppName; 42. private Label labelAppSlogan; 43. private Label labelVersion; 44. private Label labelReleased; 45. private Label labelHomePage; 46. private Label labelAppVersion; 47. private Label labelAppReleased; 48. private Label labelAppHomePage; 49. private Label labelEnvironment; 50. private Text textEnvironment; 51. private Button buttonCopyToClipboard; 52. private Button buttonClose; 53. 54. public void open() { 55. if (shell != null && !shell.isDisposed()) { 56. shell.setVisible(true); 57. shell.forceFocus(); 58. return; 59. } 60. createShell(); 61. createResources(); 62. createLogo(); 63. createLabelAppName(); 64. createLabelAppSlogan(); 65. createLabelVersion(); 66. createLabelReleased(); 67. createLabelHomePage(); 68. createLabelAppVersion(); 69. createLabelAppReleased(); 70. createLabelAppHomePage(); 71. createLabelEnvironment(); 72. createButtonClose(); 73. createButtonCopyToClipboard(); 74. createTextEnvironment(); 75. shell.pack(); 76. shell.open(); 77. } 78. 79. private void createResources() { 80. final FontData data = new FontData(); 81. data.setHeight(10); 82. data.setStyle(SWT.BOLD); 83. bold = new Font(shell.getDisplay(), data); 84. red = new Color(shell.getDisplay(), 255, 0, 0); 85. green = new Color(shell.getDisplay(), 0, 128, 0); 86. blue = new Color(shell.getDisplay(), 0, 0, 255); 87. hand = new Cursor(shell.getDisplay(), SWT.CURSOR_HAND); 88. } 89. 90. private void createShell() { 91. shell = new Shell(TrayManager.getInstance().getShell(), SWT.SHELL_TRIM); 92. final FormLayout layout = new FormLayout(); 93. layout.spacing = 6; 94. layout.marginHeight = 12; 95. layout.marginWidth = 12; 96. shell.setLocation(shell.getParent().toDisplay(100, 100)); 97. shell.setImage(IconFactory.getInstance() 98. .getUncachedIcon(“hawkscope16.png”)); 99. shell.setText(“About”); 100. shell.setLayout(layout); 101. shell.layout(); 102. } 103. 104. private FormData relativeTo(final Control top, final Control left) { 105. layout = new FormData(); 106. layout.top = new FormAttachment(top); 107. layout.left = new FormAttachment(left); 108. return layout; 109. } 110. 111. private FormData relativeToBottomRight(final Control right) { 112. layout = new FormData(); 113. layout.bottom = new FormAttachment(100, 0); 114. if (right == null) { 115. layout.right = new FormAttachment(100, 0); 116. } else { 117. layout.right = new FormAttachment(right); 118. } 119. return layout; 120. } 121. 122. private void createLogo() { 123. logo = new Canvas(shell, SWT.NONE); 124. logo.addPaintListener(new PaintListener() { 125. public void paintControl(PaintEvent e) { 126. e.gc.drawImage(IconFactory.getInstance() 127. .getUncachedIcon(“hawkscope128.png”), 0, 0); 128. } 129. }); 130. logo.addMouseListener(new MouseAdapter() { 131. @Override 132. public void mouseUp(MouseEvent event) { 133. Program.launch(Version.HOMEPAGE); 134. } 135. }); 136. logo.setCursor(hand); 137. logo.setToolTipText(“Click to visit Homepage”); 138. layout = relativeTo(null, null); 139. layout.width = 128; 140. layout.height = 128; 141. logo.setLayoutData(layout); 142. } 143. 144. private void createLabelAppName() { 145. labelAppName = new Label(shell, SWT.NONE); 146. labelAppName.setText(Version.APP_NAME); 147. labelAppName.setLayoutData(relativeTo(null, logo)); 148. labelAppName.setFont(bold); 149. } 150. 151. private void createLabelAppSlogan() { 152. labelAppSlogan = new Label(shell, SWT.NONE); 153. labelAppSlogan.setLayoutData(relativeTo(labelAppName, logo)); 154. labelAppSlogan.setText(Version.APP_SLOGAN); 155. } 156. 157. private void createLabelVersion() { 158. labelVersion = new Label(shell, SWT.NONE); 159. labelVersion.setText(“Version:”); 160. labelVersion.setFont(bold); 161. labelVersion.setLayoutData(relativeTo(labelAppSlogan, logo)); 162. } 163. 164. private void createLabelAppVersion() { 165. labelAppVersion = new Label(shell, SWT.NONE); 166. labelAppVersion.setText(Version.VERSION_NUMBER); 167. labelAppVersion.setLayoutData(relativeTo(labelAppSlogan, labelHomePage)); 168. updateLabelAppVersion(); 169. } 170. 171. private void updateLabelAppVersion() { 172. if (Version.isUpdateAvailable() == null) { 173. if (ConfigurationFactory.getConfigurationFactory() 174. .getConfiguration().checkForUpdates()) { 175. labelAppVersion.setToolTipText(“Could not get version information.”); 176. } 177. } else { 178. if (Version.isUpdateAvailable()) { 179. labelAppVersion.setForeground(red); 180. labelAppVersion.setText(Version.VERSION_NUMBER 181. + ” (Update Available!)”); 182. labelAppVersion.setToolTipText(“Click to go to update ” + 183. “download page”); 184. labelAppVersion.setCursor(hand); 185. labelAppVersion.addMouseListener(new MouseAdapter() { 186. @Override 187. public void mouseUp(final MouseEvent event) { 188. Program.launch(Version.DOWNLOAD_URL); 189. shell.dispose(); 190. } 191. }); 192. } else { 193. labelAppVersion.setText(Version.VERSION_NUMBER); 194. labelAppVersion.setToolTipText(“Latest available version!”); 195. labelAppVersion.setForeground(green); 196. } 197. } 198. } 199. 200. private void createLabelReleased() { 201. labelReleased = new Label(shell, SWT.NONE); 202. labelReleased.setText(“Released:”); 203. labelReleased.setFont(bold); 204. labelReleased.setLayoutData(relativeTo(labelVersion, logo)); 205. } 206. 207. private void createLabelAppReleased() { 208. labelAppReleased = new Label(shell, SWT.NONE); 209. labelAppReleased.setText(Version.VERSION_DATE); 210. labelAppReleased.setLayoutData(relativeTo(labelVersion, labelHomePage)); 211. } 212. 213. private void createLabelHomePage() { 214. labelHomePage = new Label(shell, SWT.NONE); 215. labelHomePage.setText(“Homepage:”); 216. labelHomePage.setFont(bold); 217. labelHomePage.setLayoutData(relativeTo(labelReleased, logo)); 218. } 219. 220. private void createLabelAppHomePage() { 221. labelAppHomePage = new Label(shell, SWT.NONE); 222. labelAppHomePage.setText(Version.HOMEPAGE); 223. labelAppHomePage.setLayoutData(relativeTo(labelReleased, labelHomePage)); 224. labelAppHomePage.setCursor(hand); 225. labelAppHomePage.setForeground(blue); 226. labelAppHomePage.setToolTipText(“Click to open in browser”); 227. labelAppHomePage.addMouseListener(new MouseAdapter() { 228. @Override 229. public void mouseUp(final MouseEvent event) { 230. Program.launch(Version.HOMEPAGE); 231. } 232. }); 233. } 234. 235. private void createLabelEnvironment() { 236. labelEnvironment = new Label(shell, SWT.NONE); 237. labelEnvironment.setText(“Environment”); 238. labelEnvironment.setFont(bold); 239. labelEnvironment.setLayoutData(relativeTo(logo, null)); 240. } 241. 242. private void createButtonClose() { 243. buttonClose = new Button(shell, SWT.PUSH); 244. buttonClose.setText(“&Close”); 245. buttonClose.setLayoutData(relativeToBottomRight(null)); 246. buttonClose.addSelectionListener(new SelectionAdapter() { 247. @Override 248. public void widgetSelected(final SelectionEvent event) { 249. shell.dispose(); 250. } 251. }); 252. } 253. 254. private void createButtonCopyToClipboard() { 255. buttonCopyToClipboard = new Button(shell, SWT.PUSH); 256. buttonCopyToClipboard.setText(“C&opy to Clipboard”); 257. buttonCopyToClipboard.setLayoutData(relativeToBottomRight(buttonClose)); 258. buttonCopyToClipboard.addSelectionListener(new SelectionAdapter() { 259. @Override 260. public void widgetSelected(final SelectionEvent event) { 261. IOUtils.copyToClipboard(Version.getEnvironmentReport()); 262. } 263. }); 264. } 265. 266. private void createTextEnvironment() { 267. textEnvironment = new Text(shell, SWT.MULTI | SWT.WRAP 268. | SWT.V_SCROLL | SWT.BORDER); 269. textEnvironment.setText(Version.getEnvironmentReport()); 270. textEnvironment.setEditable(false); 271. layout = relativeTo(labelEnvironment, null); 272. layout.right = new FormAttachment(100, 0); 273. layout.bottom = new FormAttachment(buttonClose); 274. layout.width = 500; 275. layout.height = 150; 276. textEnvironment.setLayoutData(layout); 277. } 278. 279. } package com.varaneckas.hawkscope.gui; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Cursor; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.program.Program; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import com.varaneckas.hawkscope.Version; import com.varaneckas.hawkscope.cfg.ConfigurationFactory; import com.varaneckas.hawkscope.tray.TrayManager; import com.varaneckas.hawkscope.util.IOUtils; import com.varaneckas.hawkscope.util.IconFactory; public class AboutShell { private Shell shell; private FormData layout; private Font bold; private Color red; private Color green; private Color blue; private Cursor hand; private Canvas logo; private Label labelAppName; private Label labelAppSlogan; private Label labelVersion; private Label labelReleased; private Label labelHomePage; private Label labelAppVersion; private Label labelAppReleased; private Label labelAppHomePage; private Label labelEnvironment; private Text textEnvironment; private Button buttonCopyToClipboard; private Button buttonClose; public void open() { if (shell != null && !shell.isDisposed()) { shell.setVisible(true); shell.forceFocus(); return; } createShell(); createResources(); createLogo(); createLabelAppName(); createLabelAppSlogan(); createLabelVersion(); createLabelReleased(); createLabelHomePage(); createLabelAppVersion(); createLabelAppReleased(); createLabelAppHomePage(); createLabelEnvironment(); createButtonClose(); createButtonCopyToClipboard(); createTextEnvironment(); shell.pack(); shell.open(); } private void createResources() { final FontData data = new FontData(); data.setHeight(10); data.setStyle(SWT.BOLD); bold = new Font(shell.getDisplay(), data); red = new Color(shell.getDisplay(), 255, 0, 0); green = new Color(shell.getDisplay(), 0, 128, 0); blue = new Color(shell.getDisplay(), 0, 0, 255); hand = new Cursor(shell.getDisplay(), SWT.CURSOR_HAND); } private void createShell() { shell = new Shell(TrayManager.getInstance().getShell(), SWT.SHELL_TRIM); final FormLayout layout = new FormLayout(); layout.spacing = 6; layout.marginHeight = 12; layout.marginWidth = 12; shell.setLocation(shell.getParent().toDisplay(100, 100)); shell.setImage(IconFactory.getInstance() .getUncachedIcon(“hawkscope16.png”)); shell.setText(“About”); shell.setLayout(layout); shell.layout(); } private FormData relativeTo(final Control top, final Control left) { layout = new FormData(); layout.top = new FormAttachment(top); layout.left = new FormAttachment(left); return layout; } private FormData relativeToBottomRight(final Control right) { layout = new FormData(); layout.bottom = new FormAttachment(100, 0); if (right == null) { layout.right = new FormAttachment(100, 0); } else { layout.right = new FormAttachment(right); } return layout; } private void createLogo() { logo = new Canvas(shell, SWT.NONE); logo.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { e.gc.drawImage(IconFactory.getInstance() .getUncachedIcon(“hawkscope128.png”), 0, 0); } }); logo.addMouseListener(new MouseAdapter() { @Override public void mouseUp(MouseEvent event) { Program.launch(Version.HOMEPAGE); } }); logo.setCursor(hand); logo.setToolTipText(“Click to visit Homepage”); layout = relativeTo(null, null); layout.width = 128; layout.height = 128; logo.setLayoutData(layout); } private void createLabelAppName() { labelAppName = new Label(shell, SWT.NONE); labelAppName.setText(Version.APP_NAME); labelAppName.setLayoutData(relativeTo(null, logo)); labelAppName.setFont(bold); } private void createLabelAppSlogan() { labelAppSlogan = new Label(shell, SWT.NONE); labelAppSlogan.setLayoutData(relativeTo(labelAppName, logo)); labelAppSlogan.setText(Version.APP_SLOGAN); } private void createLabelVersion() { labelVersion = new Label(shell, SWT.NONE); labelVersion.setText(“Version:”); labelVersion.setFont(bold); labelVersion.setLayoutData(relativeTo(labelAppSlogan, logo)); } private void createLabelAppVersion() { labelAppVersion = new Label(shell, SWT.NONE); labelAppVersion.setText(Version.VERSION_NUMBER); labelAppVersion.setLayoutData(relativeTo(labelAppSlogan, labelHomePage)); updateLabelAppVersion(); } private void updateLabelAppVersion() { if (Version.isUpdateAvailable() == null) { if (ConfigurationFactory.getConfigurationFactory() .getConfiguration().checkForUpdates()) { labelAppVersion.setToolTipText(“Could not get version information.”); } } else { if (Version.isUpdateAvailable()) { labelAppVersion.setForeground(red); labelAppVersion.setText(Version.VERSION_NUMBER + ” (Update Available!)”); labelAppVersion.setToolTipText(“Click to go to update ” + “download page”); labelAppVersion.setCursor(hand); labelAppVersion.addMouseListener(new MouseAdapter() { @Override public void mouseUp(final MouseEvent event) { Program.launch(Version.DOWNLOAD_URL); shell.dispose(); } }); } else { labelAppVersion.setText(Version.VERSION_NUMBER); labelAppVersion.setToolTipText(“Latest available version!”); labelAppVersion.setForeground(green); } } } private void createLabelReleased() { labelReleased = new Label(shell, SWT.NONE); labelReleased.setText(“Released:”); labelReleased.setFont(bold); labelReleased.setLayoutData(relativeTo(labelVersion, logo)); } private void createLabelAppReleased() { labelAppReleased = new Label(shell, SWT.NONE); labelAppReleased.setText(Version.VERSION_DATE); labelAppReleased.setLayoutData(relativeTo(labelVersion, labelHomePage)); } private void createLabelHomePage() { labelHomePage = new Label(shell, SWT.NONE); labelHomePage.setText(“Homepage:”); labelHomePage.setFont(bold); labelHomePage.setLayoutData(relativeTo(labelReleased, logo)); } private void createLabelAppHomePage() { labelAppHomePage = new Label(shell, SWT.NONE); labelAppHomePage.setText(Version.HOMEPAGE); labelAppHomePage.setLayoutData(relativeTo(labelReleased, labelHomePage)); labelAppHomePage.setCursor(hand); labelAppHomePage.setForeground(blue); labelAppHomePage.setToolTipText(“Click to open in browser”); labelAppHomePage.addMouseListener(new MouseAdapter() { @Override public void mouseUp(final MouseEvent event) { Program.launch(Version.HOMEPAGE); } }); } private void createLabelEnvironment() { labelEnvironment = new Label(shell, SWT.NONE); labelEnvironment.setText(“Environment”); labelEnvironment.setFont(bold); labelEnvironment.setLayoutData(relativeTo(logo, null)); } private void createButtonClose() { buttonClose = new Button(shell, SWT.PUSH); buttonClose.setText(“&Close”); buttonClose.setLayoutData(relativeToBottomRight(null)); buttonClose.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent event) { shell.dispose(); } }); } private void createButtonCopyToClipboard() { buttonCopyToClipboard = new Button(shell, SWT.PUSH); buttonCopyToClipboard.setText(“C&opy to Clipboard”); buttonCopyToClipboard.setLayoutData(relativeToBottomRight(buttonClose)); buttonCopyToClipboard.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent event) { IOUtils.copyToClipboard(Version.getEnvironmentReport()); } }); } private void createTextEnvironment() { textEnvironment = new Text(shell, SWT.MULTI | SWT.WRAP | SWT.V_SCROLL | SWT.BORDER); textEnvironment.setText(Version.getEnvironmentReport()); textEnvironment.setEditable(false); layout = relativeTo(labelEnvironment, null); layout.right = new FormAttachment(100, 0); layout.bottom = new FormAttachment(buttonClose); layout.width = 500; layout.height = 150; textEnvironment.setLayoutData(layout); } } If you compare the two versions, handcoded one is superior in most aspects. The code is smaller, more readable and text editor friendly. The window can be resized, it is better looking – in generated code the logo image was scaled due to dragging inacuracy. And, believe it or not, I’ve spent less time creating the handcoded GUI version than “drawing” the automated one and then hacking it’s generated code. Of course, if you know your tools well, you can be much more productive with a GUI builder, but I’ll rather learn the low-level GUI API than some commercial third party product that treats you like parents treat their kids with LEGO.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: