From 04c3bb3626b38eeca1f63d2f0631402520392dd4 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Tue, 5 Jul 2016 09:38:27 +0200 Subject: [PATCH 01/73] EasyShell v2.0 prototype - complete rewrite of plugin with EPL license #35 - [v2.0] new license: EPL - added table view to support adding, removing and change order of commands - new name space "de.anbos.eclipse.easyshell" Addressed enhancement requests: #9 - Editable / custom commands #11 - Change argument names #12 - Change order menue entries #14 - ability to select which of the 4 options to be visible #17 - add linux 'nemo' file browser #21 - add Xfce4 Terminal to linux presets #23 - add linux 'thunar' file browser #31 - add support of eclipse variables Bug fixes: #4 - "cd" cannot be used/called like a stand-alone program in configurations under #6 - gnome-terminal: change to working directory does not work in LMDE 201403 #29 - EasyShell v1.4.2 cannot be installed in Eclipse Neon(4.6.0M5) #30 - Compatibility Issue with Neon-M7 #45 - EasyShell not compatible with new Eclipse Neon Signed-off-by: Andre Bossert --- plugin/META-INF/MANIFEST.MF | 4 +- plugin/build.properties | 3 +- plugin/icons/console_view.gif | Bin 0 -> 582 bytes plugin/icons/copy.gif | Bin 594 -> 125 bytes plugin/icons/copy_edit.gif | Bin 0 -> 594 bytes plugin/icons/cpyqual_menu.gif | Bin 0 -> 378 bytes plugin/icons/easyshell.gif | Bin 0 -> 891 bytes plugin/icons/editor.gif | Bin 0 -> 932 bytes plugin/icons/editor_area.gif | Bin 0 -> 219 bytes plugin/icons/environment_obj.gif | Bin 0 -> 615 bytes plugin/icons/exclusion_filter_attrib.gif | Bin 0 -> 214 bytes plugin/icons/fldr_obj.gif | Bin 0 -> 216 bytes plugin/icons/run_exc.gif | Bin 0 -> 379 bytes plugin/plugin.xml | 114 +++-- .../eclipse/easyshell/plugin/Activator.java | 67 ++- .../plugin/DynamicVariableResolver.java | 51 +++ .../plugin/EditorPropertyTester.java | 44 ++ .../eclipse/easyshell/plugin/Resource.java | 39 ++ .../easyshell/plugin/ResourceUtils.java | 140 ++++++ .../easyshell/plugin/UIMessages.properties | 25 ++ .../easyshell/plugin/actions/Action.java | 220 ++++++++++ .../plugin/actions/ActionDelegate.java | 254 +++++++++++ .../plugin/commands/DefineCommands.java | 67 +++ .../plugin/handlers/CommandHandler.java | 42 ++ .../plugin/handlers/SampleHandler.java | 45 -- .../plugin/popup/actions/NewAction.java | 55 --- .../plugin/preferences/Constants.java | 38 ++ .../easyshell/plugin/preferences/Debug.java | 44 ++ ...renceInitializer.java => Initializer.java} | 17 +- .../plugin/preferences/ItemMover.java | 77 ++++ .../plugin/preferences/LinuxDesktop.java | 48 +++ .../easyshell/plugin/preferences/OS.java | 63 +++ .../preferences/PreferenceConstants.java | 27 -- .../preferences/PreferenceValueConverter.java | 74 ++++ .../preferences/PresetContentProvider.java | 35 ++ .../plugin/preferences/PresetData.java | 149 +++++++ .../PresetDataDefaultCollection.java | 356 ++++++++++++++++ .../plugin/preferences/PresetDialog.java | 222 ++++++++++ .../preferences/PresetLabelProvider.java | 50 +++ .../plugin/preferences/PresetType.java | 87 ++++ .../plugin/preferences/PresetsPage.java | 398 ++++++++++++++++++ .../plugin/preferences/PresetsStore.java | 172 ++++++++ .../easyshell/plugin/preferences/Quotes.java | 55 +++ .../preferences/SamplePreferencePage.java | 4 +- .../plugin/preferences/Tokenizer.java | 44 ++ 45 files changed, 2926 insertions(+), 204 deletions(-) create mode 100644 plugin/icons/console_view.gif create mode 100644 plugin/icons/copy_edit.gif create mode 100644 plugin/icons/cpyqual_menu.gif create mode 100644 plugin/icons/easyshell.gif create mode 100644 plugin/icons/editor.gif create mode 100644 plugin/icons/editor_area.gif create mode 100644 plugin/icons/environment_obj.gif create mode 100644 plugin/icons/exclusion_filter_attrib.gif create mode 100644 plugin/icons/fldr_obj.gif create mode 100644 plugin/icons/run_exc.gif create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/DynamicVariableResolver.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/EditorPropertyTester.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/Resource.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/ResourceUtils.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/actions/Action.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/CommandHandler.java delete mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/SampleHandler.java delete mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/popup/actions/NewAction.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Constants.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Debug.java rename plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/{PreferenceInitializer.java => Initializer.java} (76%) create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/ItemMover.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/LinuxDesktop.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/OS.java delete mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceConstants.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceValueConverter.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetContentProvider.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetData.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetDataDefaultCollection.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetDialog.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetLabelProvider.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetType.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetsPage.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetsStore.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Quotes.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Tokenizer.java diff --git a/plugin/META-INF/MANIFEST.MF b/plugin/META-INF/MANIFEST.MF index 6198ed11..d59cf01c 100644 --- a/plugin/META-INF/MANIFEST.MF +++ b/plugin/META-INF/MANIFEST.MF @@ -7,7 +7,9 @@ Bundle-Activator: de.anbos.eclipse.easyshell.plugin.Activator Bundle-Vendor: Andre Bossert Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime, - org.eclipse.core.resources + org.eclipse.core.resources, + org.eclipse.core.expressions, + org.eclipse.core.variables Bundle-RequiredExecutionEnvironment: JavaSE-1.7 Bundle-ActivationPolicy: lazy Bundle-ClassPath: target/easyshell-library.jar diff --git a/plugin/build.properties b/plugin/build.properties index 240b2c74..4ac37c5b 100644 --- a/plugin/build.properties +++ b/plugin/build.properties @@ -3,7 +3,8 @@ bin.includes = icons/,\ releases/README.TXT,\ releases/CHANGES.TXT,\ META-INF/,\ - target/easyshell-library.jar + target/easyshell-library.jar,\ + src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties src.includes = icons/,\ manpages/,\ releases/CHANGES.TXT,\ diff --git a/plugin/icons/console_view.gif b/plugin/icons/console_view.gif new file mode 100644 index 0000000000000000000000000000000000000000..a598f6082f6678d2125469b1b6ae05836796d04a GIT binary patch literal 582 zcmZ?wbhEHb6krfwc*el+`RniRKYm;JH9CfMI7f7QB}@uPn-P{fFQI%zZ0WMJ`t>0x z&Ee^7-+ugw&hCuQ?@1|{@bKl2hcCZJWp`v&P0g&Fl2O|W^(~wJw2}j2c!fnnk_{(a&fS; zGBZhvS~Xis`${M%NZgdr6|-r!)$r93l$R3}5|k6SYqr^7LG$LYCSR&E0(xS6jGH_yK|y2S%JYC06~P}0Vp9##gY=f3=5Ns%-AUURSrEuXbUd(v*17v|T_vc2xD6Ta-#@q}ZZ V;Z2|KiDuHwE3UQv^$=pP1_1Y{ELQ*k literal 594 zcmZ?wbhEHb6krfwc*el+`Rnf=KmR0GEr0jv*Qc+)fByROo^gS)J_IJ)ZIC1ImdoO<6eg6Iai|ch`(KYl-Z_w&Qo-=Dty{`%wh_n*IK&6+S{#>BaEdS}g? zuy9`2swFMU7Pc>%*EMf;?~yIV2RD`OU0=RsRqfVQbsLs9u3Fr>Y(e|+t%XN67a!VG za&TkmzV+q%)>rIYQ?+Yt^@e4Qs~5LCIMIJ)Q^u7|nYZ@VT-}uU|Nno6Ap#VCvM@3* zxHIU0+zW~m2KMz0?oG`ttxXmkot4W_b9Wps5j zXfk4vRxz9}$i=Scao16jlytap?!qMnQ+Hj7J!X%ee17cct|$M~{QZlIOcJ_%OI|o69_p&$5Z-06 psEL`Ko0;1xqTxYPJC}anf*T!+9v{#qMxsidv8UQV$-}(Rm diff --git a/plugin/icons/copy_edit.gif b/plugin/icons/copy_edit.gif new file mode 100644 index 0000000000000000000000000000000000000000..71d7c95aa8caa2e8f139d262a4e5e08aba2b88e5 GIT binary patch literal 594 zcmZ?wbhEHb6krfwc*el+`Rnf=KmR0GEr0jv*Qc+)fByROo^gS)J_IJ)ZIC1ImdoO<6eg6Iai|ch`(KYl-Z_w&Qo-=Dty{`%wh_n*IK&6+S{#>BaEdS}g? zuy9`2swFMU7Pc>%*EMf;?~yIV2RD`OU0=RsRqfVQbsLs9u3Fr>Y(e|+t%XN67a!VG za&TkmzV+q%)>rIYQ?+Yt^@e4Qs~5LCIMIJ)Q^u7|nYZ@VT-}uU|Nno6Ap#VCvM@3* zxHIU0+zW~m2KMz0?oG`ttxXmkot4W_b9Wps5j zXfk4vRxz9}$i=Scao16jlytap?!qMnQ+Hj7J!X%ee17cct|$M~{QZlIOcJ_%OI|o69_p&$5Z-06 psEL`Ko0;1xqTxYPJC}anf*T!+9v{#qMxsidv8UQV$-}(Rm literal 0 HcmV?d00001 diff --git a/plugin/icons/cpyqual_menu.gif b/plugin/icons/cpyqual_menu.gif new file mode 100644 index 0000000000000000000000000000000000000000..55e2d04ad650c6b40ae0a4fe0eee4afe371d4b34 GIT binary patch literal 378 zcmV-=0fqiYNk%w1VGsZi0M!5h`1$;2eW`bhwet1*_4oVv`uzC$`*DY{eUiC=mAiwO zy^5Z~cZ8dVoWNvrjAV0*k)_9Ndy;m9ns*xMjsgb(C=)#{Bo?j_ma!=tJue@(9}glL8V?y58X*onEGsH7E3B>- Y9wQ?bGDfzz)GbEE$15xuV<3rHC{p4=oEJ&}1VWg&h+qmLl0*!O><6Z~Zdx^q?_TE4oHJ*>bM)AeWYzinC_kFD zXl7<6ic$bLI{FY$02xT4R0^0y*nY2?vJfaEA()UbsprkapP5ss6e33dkND4xvG7_M zK7ljJZfz>fG?zvr8w&e6^ZVlEH%s>oon86yCOMMsNG>1PR+H|W++Vh*=+pdCvUYr7 zYwkdGee8YP^MQpMk3K%mE;*H`9L^s5b78FV`m3_6)8`huqO5`*ymqOuxaVMhS8>)* z;b5lt&fQD#sG5)og-{921u&uuVPr;OR7PV2K@=oG78F4hG(k{AMN(u%QB*}!*Npz%mFGN|NQjikypPF8^c3^@Zkdb;gnVc( zVj&S@eQsC7uW&%*t$zBd+F_EQSIkNI|@lNf7F?T!fG80|t5tR1WMg-sB~o2%#b-0xGCN z8b%ZqRdElyx811b4z$SD4?q3p@z0kz>1b0({-CL-8N0MPF*`CWpuCe=mK0`MsrK;ziUk)xEeo+S%SZ Pb#-&iO5;Q<7FGWR?3v&j literal 0 HcmV?d00001 diff --git a/plugin/icons/editor_area.gif b/plugin/icons/editor_area.gif new file mode 100644 index 0000000000000000000000000000000000000000..64d79074260faaa463a8897e9fac0acc5c485212 GIT binary patch literal 219 zcmZ?wbhEHb6krfwIKlt~4fgT-?c?X$*YCHVzn`I@p}yXJ|Ni;+@9+Qr`@{Tt`}_0l z=f~T}+uQ&D|9?MFV*dPwhKBg~c%V+82*?1uK=CIFBLjm7gAPa)$W8{<2nE%?l+1aH z4la0l$VWusyvarlUMEh+AeP3)3vHK=W*8^siBww5?~i77>atiDp{W#fG;S$h%aZO^ n52oyL{^0O%8!&Wi5;P zW^K{3%ZSM8&8wZ=(6_2%>V^q(w@q2FL&c#$->cj)vN5M_ZvKS*5e-}7Tel~7?n>_1 z8JIsky?b|N@7}E5J-Pk+@+a;;bMuu)*_yzb4Iy=#Lh3e#)vb+b-WuPwJ*|7!`TL)* zJo+N;*Q*jaSvO&ZUG75ryoGM1t3ArscvYqc7*3dcErW zn}RKm%C|pm*!{HQ!1E(}rZ(3X?3f*~Wk%HcX|XFN#V_hly0*7@c6Zv8_RQYqoT~?> z9NpBjdT!(Y|Nj|i3>1H|FfuU2Gw6Wq0mTUe`;mtDrskH`CL?1LQx#PS4M}M&c?Iz% zPhUU(055MJcMm&l9mRI#E)}&tO(|J9g(dO9!kf2j-5lH$BErMNAhQ3!{*b0nQBF<< z(Nkgq0)m1OO<}xj47}I5xnv9s)B~Hs`Is2^_=NZkY;0|943y#{*%{csu$Wm{|FpI; zi;v=95a7`Hpv2zSY|*pl$EMT<=XS;zj-QSn+Xckqmt;(Nw3J(1!nuioQ7DCj$GOR6 ci-yw^w~1o!1L_0?7rS;#7^W`bVPUWa0H==RQ2+n{ literal 0 HcmV?d00001 diff --git a/plugin/icons/exclusion_filter_attrib.gif b/plugin/icons/exclusion_filter_attrib.gif new file mode 100644 index 0000000000000000000000000000000000000000..92bce142367853f9291c1d33ffeb406e61b5799b GIT binary patch literal 214 zcmZ?wbhEHb6krfwIKseCR#tA|5}RMv5}s01-ZCq`d4XU5Uf-zLe}CWq{dDZ_M<6=> z_tWt|&*m-3hadx_;xW+wPdaF)Nk--`OJfBW0 literal 0 HcmV?d00001 diff --git a/plugin/icons/fldr_obj.gif b/plugin/icons/fldr_obj.gif new file mode 100644 index 0000000000000000000000000000000000000000..51e703b1b9c671baa2be0f6525edb3b69403370d GIT binary patch literal 216 zcmZ?wbhEHb6krfwIKsg2wj(b5!P~sjn^4pBFDXFJ7TPNb)}zFdzZN zpDc_F4AKlbATf}g46LCK)cR5~=VfGBty!EmMJ+qTijl!k<;;`cOWYDXbj&=28jDUI znIPA;;-J&oD09KqYe6rnb~B%5E3$|-Qf6T{aP*iM?lCLeYNChZ zME|t4Kq*J#ax2FU508od{@|VOltj+J(UOww!N5}U3iQCI3ZqHwGu%qFO+M$;f|G|KP zbfEZ?g^__lk3k2d733!dwiyo73p{kh9NV1~0xTMO)-@+?HCpL1C+*_|jkQs$L%3SK zWZD#%Uw+AK^#3sVq2$yax7_cq>g;#(C^lABHOjI%u}OEy<@M@F%Q8AK@K5dOm7mJO z;KV30f4Z*Rd;#G}fjokO)8$r)3o+Lza0p5E$no(>iVJg;1ab?@$%#scNeOe;IkR(c Y3G?y_b8(z@@nG_1@(Z}@>d0UX09ibCp#T5? literal 0 HcmV?d00001 diff --git a/plugin/plugin.xml b/plugin/plugin.xml index a4201c36..23694d10 100644 --- a/plugin/plugin.xml +++ b/plugin/plugin.xml @@ -5,94 +5,90 @@ + id="de.anbos.eclipse.easyshell.plugin.commands.execute"> + + + + + class="de.anbos.eclipse.easyshell.plugin.handlers.CommandHandler" + commandId="de.anbos.eclipse.easyshell.plugin.commands.execute"> - - - - + locationURI="popup:org.eclipse.ui.popup.any?after=group.open"> - - + icon="icons/easyshell.gif" + id="de.anbos.eclipse.easyshell.plugin.menu" + label="EasyShell"> + + + + + + - - - - + allPopups="true" + class="de.anbos.eclipse.easyshell.plugin.commands.DefineCommands" + locationURI="popup:de.anbos.eclipse.easyshell.plugin.menu"> - - - - - - - - - - + class="de.anbos.eclipse.easyshell.plugin.preferences.PresetsPage" + id="de.anbos.eclipse.easyshell.plugin.preferences.PresetsPage" + name="EasyShell"> + class="de.anbos.eclipse.easyshell.plugin.preferences.Initializer"> + + + + + + + + diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java index d2037bbe..7ffc17ce 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015 Andre Bossert. + * Copyright (c) 2014 - 2016 Andre Bossert. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -11,21 +11,34 @@ package de.anbos.eclipse.easyshell.plugin; +import java.net.URL; +import java.text.MessageFormat; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.ImageRegistry; import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; +import de.anbos.eclipse.easyshell.plugin.preferences.Constants; + /** * The activator class controls the plug-in life cycle */ public class Activator extends AbstractUIPlugin { - // The plug-in ID - public static final String PLUGIN_ID = "de.anbos.eclipse.easyshell.plugin"; //$NON-NLS-1$ - // The shared instance private static Activator plugin; + //Resource bundle. + private ResourceBundle resourceBundle; + /** * The constructor */ @@ -39,6 +52,13 @@ public Activator() { public void start(BundleContext context) throws Exception { super.start(context); plugin = this; + try { + //resourceBundle = Platform.getResourceBundle(context.getBundle()); + resourceBundle = ResourceBundle.getBundle(Constants.PLUGIN_ID + ".UIMessages"); //$NON-NLS-1$ + } catch (MissingResourceException x) { + resourceBundle = null; + } + getImageRegistry(); } /* @@ -66,7 +86,44 @@ public static Activator getDefault() { * @param path the path * @return the image descriptor */ + /* public static ImageDescriptor getImageDescriptor(String path) { - return imageDescriptorFromPlugin(PLUGIN_ID, path); + return imageDescriptorFromPlugin(Constants.PLUGIN_ID, path); } + */ + public static ImageDescriptor getImageDescriptor(String id) { + return getDefault().getImageRegistry().getDescriptor(id); + } + protected void initializeImageRegistry(ImageRegistry registry) { + Bundle bundle = Platform.getBundle(Constants.PLUGIN_ID); + addImageToRegistry(registry, bundle, Constants.IMAGE_PATH + Constants.IMAGE_OPEN, Constants.IMAGE_OPEN); + addImageToRegistry(registry, bundle, Constants.IMAGE_PATH + Constants.IMAGE_RUN, Constants.IMAGE_RUN); + addImageToRegistry(registry, bundle, Constants.IMAGE_PATH + Constants.IMAGE_EXPLORE, Constants.IMAGE_EXPLORE); + addImageToRegistry(registry, bundle, Constants.IMAGE_PATH + Constants.IMAGE_CLIPBOARD, Constants.IMAGE_CLIPBOARD); + } + + protected void addImageToRegistry(ImageRegistry registry, Bundle bundle, String imagePath, String image_id) { + IPath path = new Path(imagePath); + URL url = FileLocator.find(bundle, path, null); + ImageDescriptor desc = ImageDescriptor.createFromURL(url); + registry.put(image_id, desc); + } + + public ResourceBundle getResourceBundle() { + return resourceBundle; + } + + public static String getResourceString(String key) { + ResourceBundle bundle = Activator.getDefault().getResourceBundle(); + try { + return (bundle != null) ? bundle.getString(key) : key; + } catch (MissingResourceException e) { + return key; + } + } + + public static String getResourceString(String key, Object[] args) { + return MessageFormat.format(getResourceString(key),args); + } + } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/DynamicVariableResolver.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/DynamicVariableResolver.java new file mode 100644 index 00000000..b5697a99 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/DynamicVariableResolver.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.variables.IDynamicVariable; +import org.eclipse.core.variables.IDynamicVariableResolver; + +public class DynamicVariableResolver implements IDynamicVariableResolver { + + private static String[] args = new String[6]; + + @Override + public String resolveValue(IDynamicVariable variable, String argument) + throws CoreException { + if (variable.getName().equals("easyshell")) { + if (argument.equals("drive")) { + return args[0]; + } else if (argument.equals("container_loc")) { + return args[1]; + } else if (argument.equals("resource_loc")) { + return args[2]; + } else if (argument.equals("resource_name")) { + return args[3]; + } else if (argument.equals("project_name")) { + return args[4]; + } else if (argument.equals("line_separator")) { + return args[5]; + } + } + return null; + } + + public String[] getArgs() { + return args; + } + + public static void setArgs(String[] args) { + DynamicVariableResolver.args = args; + } + +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/EditorPropertyTester.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/EditorPropertyTester.java new file mode 100644 index 00000000..69870103 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/EditorPropertyTester.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin; + +import org.eclipse.core.expressions.PropertyTester; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IWorkbenchPart; + +import de.anbos.eclipse.easyshell.plugin.actions.ActionDelegate; + +public class EditorPropertyTester extends PropertyTester { + + public EditorPropertyTester() { + super(); + } + + public boolean test(Object receiver, String property, Object[] args, Object expectedValue) { + if("hasResourceSelection".equals(property) && receiver instanceof IWorkbenchPart){ + return hasResourceSelection((IWorkbenchPart)receiver) != null; + } + return false; + } + + static public ActionDelegate hasResourceSelection(IWorkbenchPart part) { + ISelection selection = ResourceUtils.getResourceSelection(part); + if (selection != null) { + ActionDelegate action = new ActionDelegate(); + action.selectionChanged(null, selection); + if (action.isEnabled()) + return action; + } + return null; + } + +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/Resource.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/Resource.java new file mode 100644 index 00000000..8d1aeef1 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/Resource.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin; + +import java.io.File; + +public class Resource { + + private File file = null; + private String projectName = null; + + public Resource(Resource myRes) { + file = myRes.getFile(); + projectName = myRes.getProjectName(); + } + + public Resource(File myFile, String myProjectName) { + file = myFile; + projectName = myProjectName; + } + + public File getFile() { + return file; + } + + public String getProjectName() { + return projectName; + } + +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/ResourceUtils.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/ResourceUtils.java new file mode 100644 index 00000000..3ab58b36 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/ResourceUtils.java @@ -0,0 +1,140 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin; + +import java.io.File; +//import java.net.URI; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IPath; +//import org.eclipse.jdt.internal.core.JarPackageFragmentRoot; +//import org.eclipse.jdt.internal.core.PackageFragment; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPart; +//import org.eclipse.ui.ide.FileStoreEditorInput; + + +public class ResourceUtils { + + static public ISelection getResourceSelection(IWorkbenchPart part) { + ISelection selection = null; + if (part != null) { + if (part instanceof IEditorPart) { + Resource file = getResource((IEditorPart)part); + if (file != null) { + selection = new StructuredSelection(file); + } + } else { + try { + selection = part.getSite().getSelectionProvider().getSelection(); + } catch(Exception e) { + // no op + } + } + } + return selection; + } + + static public Resource getResource(Object myObj) { + Object object = null; + + if (myObj instanceof IEditorPart) { + IEditorPart editorPart = (IEditorPart)myObj; + IEditorInput input = editorPart.getEditorInput(); + Object adapter = input.getAdapter(IFile.class); + if(adapter instanceof IFile){ + object = (IFile) adapter; + } else { + adapter = editorPart.getAdapter(IFile.class); + if(adapter instanceof IFile){ + object = (IFile) adapter; + } else { + object = input; + } + } + } else { + object = myObj; + } + + if (object instanceof Resource) { + return new Resource((Resource)object); + } + + String projectName = null; + if (object instanceof IFile) { + projectName = ((IFile) object).getProject().getName(); + return new Resource(((IFile) object).getLocation().toFile(),projectName); + } + if (object instanceof File) { + return new Resource((File) object,projectName); + } + if (object instanceof IAdaptable) { + IAdaptable adaptable = (IAdaptable) object; + IFile ifile = (IFile) adaptable.getAdapter(IFile.class); + if (ifile != null) { + projectName = ifile.getProject().getName(); + return new Resource(ifile.getLocation().toFile(),projectName); + } + IResource ires = (IResource) adaptable.getAdapter(IResource.class); + if (ires != null) { + projectName = ires.getProject().getName(); + // virtual (not present in file system) folder has no location + // there for cannot be handled with EasyShell + // see https://sourceforge.net/tracker/?func=detail&aid=3521852&group_id=99802&atid=630351 + IPath path = ires.getLocation(); + if (path != null) { + return new Resource(path.toFile(),projectName); + } + } + /* + if (adaptable instanceof PackageFragment + && ((PackageFragment) adaptable).getPackageFragmentRoot() instanceof JarPackageFragmentRoot) { + return new Resource(getJarFile(((PackageFragment) adaptable) + .getPackageFragmentRoot()),projectName); + } else if (adaptable instanceof JarPackageFragmentRoot) { + return new Resource(getJarFile(adaptable),projectName); + } else if (adaptable instanceof FileStoreEditorInput) { + URI fileuri = ((FileStoreEditorInput) adaptable).getURI(); + return new Resource(new File(fileuri.getPath()),projectName); + } + */ + File file = (File) adaptable.getAdapter(File.class); + if (file != null) { + return new Resource(file,projectName); + } + } + return null; + } + + /* + static public File getJarFile(IAdaptable adaptable) { + JarPackageFragmentRoot jpfr = (JarPackageFragmentRoot) adaptable; + File resource = (File) jpfr.getPath().makeAbsolute().toFile(); + if (!((File) resource).exists()) { + File projectFile = + new File( + jpfr + .getJavaProject() + .getProject() + .getLocation() + .toOSString()); + resource = new File(projectFile.getParent() + resource.toString()); + } + return resource; + } + */ +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties new file mode 100644 index 00000000..c84c11ac --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties @@ -0,0 +1,25 @@ +easyshell.plugin.name=EasyShell +easyshell.properties.main.page.title=EasyShell +easyshell.properties.presets.page.title=Presets +easyshell.actionset.name=EasyShell + +easyshell.preseteditor.table.header.column0.title=Name +easyshell.preseteditor.table.header.column1.title=Command +easyshell.preseteditor.button.add=Add... +easyshell.preseteditor.button.edit=Edit... +easyshell.preseteditor.button.remove=Remove +easyshell.preseteditor.button.up=Up +easyshell.preseteditor.button.down=Down + +easyshell.preseteditor.dialog.new.title=Create new preset +easyshell.preseteditor.dialog.edit.title=Edit existing preset +easyshell.preseteditor.dialog.title=Line selection + +easyshell.preseteditor.dialog.error.incompletedata.title=Missing or Wrong command detected +easyshell.preseteditor.dialog.error.type.text=Please choose a type +easyshell.preseteditor.dialog.error.name.text=Please enter a valid name +easyshell.preseteditor.dialog.error.value.text=Please enter a valid command +easyshell.preseteditor.dialog.active.label=set active: +easyshell.preseteditor.dialog.combo.label=select type: +easyshell.preseteditor.dialog.name.label=enter name: +easyshell.preseteditor.dialog.value.label=enter command: \ No newline at end of file diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/Action.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/Action.java new file mode 100644 index 00000000..b05f5dbc --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/Action.java @@ -0,0 +1,220 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.actions; + +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.IMenuCreator; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.swt.events.HelpListener; +import org.eclipse.swt.widgets.Event; + +public class Action implements IAction { + + private String id; + + public Action(String myId) { + id = myId; + } + + @Override + public void addPropertyChangeListener(IPropertyChangeListener listener) { + // TODO Auto-generated method stub + + } + + @Override + public int getAccelerator() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String getActionDefinitionId() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getDescription() { + // TODO Auto-generated method stub + return null; + } + + @Override + public ImageDescriptor getDisabledImageDescriptor() { + // TODO Auto-generated method stub + return null; + } + + @Override + public HelpListener getHelpListener() { + // TODO Auto-generated method stub + return null; + } + + @Override + public ImageDescriptor getHoverImageDescriptor() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getId() { + // TODO Auto-generated method stub + return null; + } + + @Override + public ImageDescriptor getImageDescriptor() { + // TODO Auto-generated method stub + return null; + } + + @Override + public IMenuCreator getMenuCreator() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getStyle() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String getText() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getToolTipText() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isChecked() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isEnabled() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isHandled() { + // TODO Auto-generated method stub + return false; + } + + @Override + public void removePropertyChangeListener(IPropertyChangeListener listener) { + // TODO Auto-generated method stub + + } + + @Override + public void run() { + // TODO Auto-generated method stub + + } + + @Override + public void runWithEvent(Event event) { + // TODO Auto-generated method stub + + } + + @Override + public void setActionDefinitionId(String id) { + // TODO Auto-generated method stub + + } + + @Override + public void setChecked(boolean checked) { + // TODO Auto-generated method stub + + } + + @Override + public void setDescription(String text) { + // TODO Auto-generated method stub + + } + + @Override + public void setDisabledImageDescriptor(ImageDescriptor newImage) { + // TODO Auto-generated method stub + + } + + @Override + public void setEnabled(boolean enabled) { + // TODO Auto-generated method stub + + } + + @Override + public void setHelpListener(HelpListener listener) { + // TODO Auto-generated method stub + + } + + @Override + public void setHoverImageDescriptor(ImageDescriptor newImage) { + // TODO Auto-generated method stub + + } + + @Override + public void setId(String id) { + // TODO Auto-generated method stub + + } + + @Override + public void setImageDescriptor(ImageDescriptor newImage) { + // TODO Auto-generated method stub + + } + + @Override + public void setMenuCreator(IMenuCreator creator) { + // TODO Auto-generated method stub + + } + + @Override + public void setText(String text) { + // TODO Auto-generated method stub + + } + + @Override + public void setToolTipText(String text) { + // TODO Auto-generated method stub + + } + + @Override + public void setAccelerator(int keycode) { + // TODO Auto-generated method stub + + } +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java new file mode 100644 index 00000000..0a3b960b --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java @@ -0,0 +1,254 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.actions; + +import java.util.StringTokenizer; + +import org.eclipse.core.variables.IStringVariableManager; +import org.eclipse.core.variables.VariablesPlugin; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.dnd.TextTransfer; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IObjectActionDelegate; +import org.eclipse.ui.IWorkbenchPart; + +import de.anbos.eclipse.easyshell.plugin.DynamicVariableResolver; +import de.anbos.eclipse.easyshell.plugin.Resource; +import de.anbos.eclipse.easyshell.plugin.ResourceUtils; +import de.anbos.eclipse.easyshell.plugin.preferences.PresetType; +import de.anbos.eclipse.easyshell.plugin.preferences.Quotes; + +public class ActionDelegate implements IObjectActionDelegate { + + private Resource[] resource = null; + private IStructuredSelection currentSelection; + private String commandValue = null; + private PresetType commandType = PresetType.presetTypeUnknown; + + public PresetType getCommandType() { + return commandType; + } + + public void setCommandType(PresetType commandType) { + this.commandType = commandType; + } + + public String getCommandValue() { + return commandValue; + } + + public void setCommandValue(String commandValue) { + this.commandValue = commandValue; + } + + public ActionDelegate() { + super(); + } + + public void setActivePart(IAction action, IWorkbenchPart targetPart) { + } + + public void run(IAction action) { + if (!isEnabled()) { + MessageDialog.openInformation( + new Shell(), + "Easy Shell", + "Wrong Selection"); + //Activator.log("Wrong Selection"); + return; + } + + // get the ID + String ActionIDStr = action.getId(); + //Activator.getDefault().sysout(true, "Action ID: >" + ActionIDStr + "<"); + + // String for all commands in case of clipboard + String cmdAll = null; + if (commandType == PresetType.presetTypeClipboard) { + cmdAll = new String(); + } + + IStringVariableManager variableManager = VariablesPlugin.getDefault().getStringVariableManager(); + + for (int i=0;i" + full_path + "<"); + //Activator.getDefault().sysout(true, "parent_path: >" + parent_path + "<"); + //Activator.getDefault().sysout(true, "file_name : >" + file_name + "<"); + + // Try to extract drive on Win32 + if (full_path.indexOf(":") != -1) { + drive = full_path.substring(0, full_path.indexOf(":")); + } + + try { + String target = commandValue; + //Quotes quotes = Activator.getDefault().getQuotes(InstanceIDNum); + Quotes quotes = Quotes.quotesNo; + String[] args = new String[6]; + // args format + args[0] = drive; // {0} == ${easyshell:drive} + args[1] = autoQuotes(parent_path, quotes); // {1} == ${easyshell:container_loc} + args[2] = autoQuotes(full_path, quotes); // {2} == ${easyshell:resource_loc} + args[3] = autoQuotes(file_name, quotes); // {3} == ${easyshell:resource_name} + args[4] = resource[i].getProjectName(); // {4} == ${easyshell:project_name} + if (args[4] == null) + args[4] = "EasyShell"; + args[5] = System.getProperty("line.separator"); // {5} == ${easyshell:line_separator} + // variable format + DynamicVariableResolver.setArgs(args); + // handling copy to clipboard + if (commandType == PresetType.presetTypeClipboard) { + String cmd = fixQuotes(variableManager.performStringSubstitution(target, false), quotes); + //Activator.getDefault().sysout(true, "--- clp: >"); + cmdAll += cmd; + //Activator.getDefault().sysout(true, cmd); + //Activator.getDefault().sysout(true, "--- clp: <"); + } + // handling command line + else { + // string tokenizer enabled ? + //if (Activator.getDefault().isTokenizer(InstanceIDNum)) + if (true) + { + StringTokenizer st = new StringTokenizer(target); + String[] cmds = new String[st.countTokens()]; + int c = 0; + //Activator.getDefault().sysout(true, "--- cmd: >"); + while (st.hasMoreElements()) { + cmds[c] = fixQuotes(variableManager.performStringSubstitution(st.nextToken(), false), quotes); + //Activator.getDefault().sysout(true, cmds[c]); + c++; + } + //Activator.getDefault().sysout(true, "--- cmd: <"); + Runtime.getRuntime().exec(cmds); + } + // the old command line passing without string tokenizer + else { + String cmd = fixQuotes(variableManager.performStringSubstitution(target, false), quotes); + //Activator.getDefault().sysout(true, "--- cmd: >"); + Runtime.getRuntime().exec(cmd); + //Activator.getDefault().sysout(true, cmd); + //Activator.getDefault().sysout(true, "--- cmd: <"); + } + } + + } catch (Exception e) { + //Activator.log(e); + } + + } else { + + MessageDialog.openInformation( + new Shell(), + "Easy Shell", + "Unable to open shell"); + //Activator.log("Unable to open shell"); + return; + + } + } + + // handling copy to clipboard + if ((commandType == PresetType.presetTypeClipboard) && (cmdAll != null) && (cmdAll.length() != 0)) { + Clipboard clipboard = new Clipboard(Display.getCurrent()); + TextTransfer textTransfer = TextTransfer.getInstance(); + Transfer[] transfers = new Transfer[]{textTransfer}; + Object[] data = new Object[]{cmdAll}; + clipboard.setContents(data, transfers); + clipboard.dispose(); + } + } + + public void selectionChanged(IAction action, ISelection selection) { + currentSelection = selection instanceof IStructuredSelection ? (IStructuredSelection)selection : null; + } + + public boolean isEnabled() + { + boolean enabled = false; + if (currentSelection != null) + { + Object[] selectedObjects = currentSelection.toArray(); + if (selectedObjects.length >= 1) + { + resource = new Resource[selectedObjects.length]; + for (int i=0;i commandParamametersMap = new HashMap(); + commandParamametersMap.put(paramId1, paramValue1); + commandParamametersMap.put(paramId2, paramValue2); + param.parameters = commandParamametersMap; + CommandContributionItem item = new CommandContributionItem(param); + item.setVisible(true); + additions.addContributionItem(item, null); + } +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/CommandHandler.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/CommandHandler.java new file mode 100644 index 00000000..6f9c58ce --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/CommandHandler.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.handlers; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.action.IAction; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.handlers.HandlerUtil; + +import de.anbos.eclipse.easyshell.plugin.EditorPropertyTester; +import de.anbos.eclipse.easyshell.plugin.actions.Action; +import de.anbos.eclipse.easyshell.plugin.actions.ActionDelegate; +import de.anbos.eclipse.easyshell.plugin.preferences.PresetType; + +public class CommandHandler extends AbstractHandler { + + public Object execute(ExecutionEvent event) throws ExecutionException { + IWorkbenchPart activePart = HandlerUtil.getActivePart(event); + ActionDelegate action = EditorPropertyTester.hasResourceSelection(activePart); + if (action != null) { + String commandID = event.getCommand().getId(); + String commandType = event.getParameter("de.anbos.eclipse.easyshell.plugin.commands.parameter.type"); + String commanValue = event.getParameter("de.anbos.eclipse.easyshell.plugin.commands.parameter.value"); + action.setCommandType(PresetType.getFromAction(commandType)); + action.setCommandValue(commanValue); + Action act = new Action(commandID); + action.run((IAction)act); + } + return null; + } +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/SampleHandler.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/SampleHandler.java deleted file mode 100644 index d7f95c7d..00000000 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/SampleHandler.java +++ /dev/null @@ -1,45 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Andre Bossert. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Andre Bossert - initial API and implementation and/or initial documentation - *******************************************************************************/ - -package de.anbos.eclipse.easyshell.plugin.handlers; - -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.ui.IWorkbenchWindow; -import org.eclipse.ui.handlers.HandlerUtil; -import org.eclipse.jface.dialogs.MessageDialog; - -/** - * Our sample handler extends AbstractHandler, an IHandler base class. - * @see org.eclipse.core.commands.IHandler - * @see org.eclipse.core.commands.AbstractHandler - */ -public class SampleHandler extends AbstractHandler { - /** - * The constructor. - */ - public SampleHandler() { - } - - /** - * the command has been executed, so extract extract the needed information - * from the application context. - */ - public Object execute(ExecutionEvent event) throws ExecutionException { - IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event); - MessageDialog.openInformation( - window.getShell(), - "EasyShell", - "Hello, Eclipse world"); - return null; - } -} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/popup/actions/NewAction.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/popup/actions/NewAction.java deleted file mode 100644 index 999b36d1..00000000 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/popup/actions/NewAction.java +++ /dev/null @@ -1,55 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Andre Bossert. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Andre Bossert - initial API and implementation and/or initial documentation - *******************************************************************************/ - -package de.anbos.eclipse.easyshell.plugin.popup.actions; - -import org.eclipse.jface.action.IAction; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.ui.IObjectActionDelegate; -import org.eclipse.ui.IWorkbenchPart; - -public class NewAction implements IObjectActionDelegate { - - private Shell shell; - - /** - * Constructor for Action1. - */ - public NewAction() { - super(); - } - - /** - * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart) - */ - public void setActivePart(IAction action, IWorkbenchPart targetPart) { - shell = targetPart.getSite().getShell(); - } - - /** - * @see IActionDelegate#run(IAction) - */ - public void run(IAction action) { - MessageDialog.openInformation( - shell, - "EasyShell", - "New Action was executed."); - } - - /** - * @see IActionDelegate#selectionChanged(IAction, ISelection) - */ - public void selectionChanged(IAction action, ISelection selection) { - } - -} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Constants.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Constants.java new file mode 100644 index 00000000..e5c771cf --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Constants.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +public interface Constants { + + // Plugin + public static final String PLUGIN_ID = "de.anbos.eclipse.easyshell.plugin"; //$NON-NLS-1$ + + // Images + public static final String IMAGE_PATH = "icons/"; + public static final String IMAGE_UNKNOWN = "sample.gif"; + public static final String IMAGE_OPEN = "prompt.gif"; + public static final String IMAGE_RUN = "run_exc.gif"; + public static final String IMAGE_EXPLORE = "fldr_obj.gif"; + public static final String IMAGE_CLIPBOARD = "copy.gif"; + public static final String IMAGE_OTHER = "editor.gif"; + + // Preferences + public static final String PREF_PRESETS = "PRESETS"; //$NON-NLS-1$ + + // Actions + public static final String ACTION_UNKNOWN = "de.anbos.eclipse.easyshell.plugin.commands.Unknown"; + public static final String ACTION_OPEN = "de.anbos.eclipse.easyshell.plugin.commands.Open"; + public static final String ACTION_RUN = "de.anbos.eclipse.easyshell.plugin.commands.Run"; + public static final String ACTION_EXPLORE = "de.anbos.eclipse.easyshell.plugin.commands.Explore"; + public static final String ACTION_CLIPBOARD = "de.anbos.eclipse.easyshell.plugin.commands.Clipboard"; + public static final String ACTION_OTHER = "de.anbos.eclipse.easyshell.plugin.commands.Other"; +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Debug.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Debug.java new file mode 100644 index 00000000..da7c53c9 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Debug.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +/** + * Debug. + */ +public enum Debug { + debugNo(0, "No"), + debugYes(1, "Yes"); + // attributes + private final int id; + private final String mode; + // construct + Debug(int id, String mode) { + this.id = id; + this.mode = mode; + } + public int getId() { + return id; + } + public String getMode() { + return mode; + } + public static Debug getFromId(int id) { + Debug ret = debugNo; + for(int i = 0; i < Debug.values().length; i++) { + if (Debug.values()[i].getId() == id) { + ret = Debug.values()[i]; + break; + } + } + return ret; + } +} \ No newline at end of file diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceInitializer.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java similarity index 76% rename from plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceInitializer.java rename to plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java index 91412695..84773d3f 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceInitializer.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015 Andre Bossert. + * Copyright (c) 2014 - 2016 Andre Bossert. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -16,22 +16,19 @@ import de.anbos.eclipse.easyshell.plugin.Activator; -/** - * Class used to initialize default preference values. - */ -public class PreferenceInitializer extends AbstractPreferenceInitializer { +public class Initializer extends AbstractPreferenceInitializer { - /* - * (non-Javadoc) - * - * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences() - */ public void initializeDefaultPreferences() { IPreferenceStore store = Activator.getDefault().getPreferenceStore(); + String defaultPresets = PreferenceValueConverter.asString(PresetDataDefaultCollection.getDefaultPresetsStatic()); + store.setDefault(Constants.PREF_PRESETS,defaultPresets); + //getDefaultPresets(); + /* store.setDefault(PreferenceConstants.P_BOOLEAN, true); store.setDefault(PreferenceConstants.P_CHOICE, "choice2"); store.setDefault(PreferenceConstants.P_STRING, "Default value"); + */ } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/ItemMover.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/ItemMover.java new file mode 100644 index 00000000..3589c6d6 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/ItemMover.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableItem; + +public class ItemMover implements SelectionListener { + + private Table table; + private PresetsStore store; + + private PresetData currentSelection; + + public ItemMover(Table table, PresetsStore store) { + this.table = table; + this.store = store; + table.addSelectionListener(this); + } + + public void moveCurrentSelectionUp() { + if(currentSelection == null) { + return; + } + PresetData previousElement = store.getPreviousElement(currentSelection); + if(previousElement == null) { + return; + } + int newPosition = previousElement.getPosition(); + int oldPosition = currentSelection.getPosition(); + previousElement.setPosition(oldPosition); + currentSelection.setPosition(newPosition); + } + + public void moveCurrentSelectionDown() { + if(currentSelection == null) { + return; + } + PresetData nextElement = store.getNextElement(currentSelection); + if(nextElement == null) { + return; + } + int newPosition = nextElement.getPosition(); + int oldPosition = currentSelection.getPosition(); + nextElement.setPosition(oldPosition); + currentSelection.setPosition(newPosition); + } + + public void widgetDefaultSelected(SelectionEvent e) { + } + + public void widgetSelected(SelectionEvent e) { + TableItem item = null; + try { + item = table.getSelection()[0]; + } catch(Throwable t) { + currentSelection = null; + return; + } + if(item == null || !(item.getData() instanceof PresetData)) { + currentSelection = null; + return; + } + currentSelection = (PresetData)item.getData(); + } +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/LinuxDesktop.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/LinuxDesktop.java new file mode 100644 index 00000000..4ee1069c --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/LinuxDesktop.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +/** + * Linux desktops. + */ +public enum LinuxDesktop { + desktopUnknown(0, "Unknown"), + desktopKde(1, "KDE"), + desktopGnome(2, "Gnome"), + desktopCinnamon(3, "Cinnamon"), + desktopCde(4, "CDE"), + desktopXfce(5, "Xfce"); + // attributes + private final int id; + private final String name; + // construct + LinuxDesktop(int id, String name) { + this.id = id; + this.name = name; + } + public int getId() { + return id; + } + public String getName() { + return name; + } + public static LinuxDesktop getFromId(int id) { + LinuxDesktop ret = desktopUnknown; + for(int i = 0; i < LinuxDesktop.values().length; i++) { + if (LinuxDesktop.values()[i].getId() == id) { + ret = LinuxDesktop.values()[i]; + break; + } + } + return ret; + } +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/OS.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/OS.java new file mode 100644 index 00000000..ff9b76cb --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/OS.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +import java.util.ArrayList; +import java.util.List; + +public enum OS { + osUnknown(0, "Unknown"), + osWindows(1, "Windows"), + osLinux(2, "Linux"), + osMacOSX(3, "MAC OS X"); + // attributes + private final int id; + private final String name; + // construct + OS(int id, String name) { + this.id = id; + this.name = name; + } + public int getId() { + return id; + } + public String getName() { + return name; + } + public static OS getFromId(int id) { + OS ret = osUnknown; + for(int i = 0; i < OS.values().length; i++) { + if (OS.values()[i].getId() == id) { + ret = OS.values()[i]; + break; + } + } + return ret; + } + public static OS getFromName(String name) { + OS ret = osUnknown; + for(int i = 0; i < OS.values().length; i++) { + if (OS.values()[i].getName().equals(name)) { + ret = OS.values()[i]; + break; + } + } + return ret; + } + public static List getNamesAsList() { + List list = new ArrayList(); + for(int i = 0; i < OS.values().length; i++) { + list.add(OS.values()[i].getName()); + } + return list; + } +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceConstants.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceConstants.java deleted file mode 100644 index d992dd82..00000000 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceConstants.java +++ /dev/null @@ -1,27 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Andre Bossert. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Andre Bossert - initial API and implementation and/or initial documentation - *******************************************************************************/ - -package de.anbos.eclipse.easyshell.plugin.preferences; - -/** - * Constant definitions for plug-in preferences - */ -public class PreferenceConstants { - - public static final String P_PATH = "pathPreference"; - - public static final String P_BOOLEAN = "booleanPreference"; - - public static final String P_CHOICE = "choicePreference"; - - public static final String P_STRING = "stringPreference"; - -} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceValueConverter.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceValueConverter.java new file mode 100644 index 00000000..fbd583ab --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceValueConverter.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.StringTokenizer; + +import org.eclipse.core.internal.preferences.Base64; + +public class PreferenceValueConverter { + + // Constant ---------------------------------------------------------------- + + public static String VALUE_DELIMITER = "|"; //$NON-NLS-1$ + public static String ITEM_DELIMITER = "#"; //$NON-NLS-1$ + + // Static ------------------------------------------------------------------ + + public static String asString(List items) { + StringBuffer buffer = new StringBuffer(); + for(PresetData item : items) { + buffer.append(asString(item)); + buffer.append(ITEM_DELIMITER); + } + return buffer.toString(); + } + + public static final String asString(PresetData data) { + String position = Integer.toString(data.getPosition()); + String enabled = Boolean.toString(data.isEnabled()); + String id = data.getId(); + String name = data.getName(); + String type = data.getType().getName(); + String value = data.getValue(); + String os = data.getOs().getName(); + return position + VALUE_DELIMITER + enabled + VALUE_DELIMITER + id + VALUE_DELIMITER + name + VALUE_DELIMITER + type + VALUE_DELIMITER + value + VALUE_DELIMITER + os + VALUE_DELIMITER; + } + + /* + public static final String asStringBase64(PresetData data) { + String position = Base64.encode(Integer.toString(data.getPosition()).getBytes(StandardCharsets.UTF_8)).toString(); + String checked = Base64.encode(Boolean.toString(data.isEnabled()).getBytes(StandardCharsets.UTF_8)).toString(); + String name = Base64.encode(data.getName().getBytes(StandardCharsets.UTF_8)).toString(); + String type = Base64.encode(data.getType().getBytes(StandardCharsets.UTF_8)).toString(); + String value = Base64.encode(data.getValue().getBytes(StandardCharsets.UTF_8)).toString(); + return position + VALUE_DELIMITER + checked + VALUE_DELIMITER + name + VALUE_DELIMITER + type + VALUE_DELIMITER + value + VALUE_DELIMITER; + } + */ + + public static PresetData[] asPresetDataArray(String value) { + StringTokenizer tokenizer = new StringTokenizer(value,ITEM_DELIMITER); + PresetData[] items = new PresetData[tokenizer.countTokens()]; + for(int i = 0 ; i < items.length ; i++) { + items[i] = asPresetData(tokenizer.nextToken()); + } + return items; + } + + public static PresetData asPresetData(String value) { + PresetData data = new PresetData(); + data.fillTokens(value, VALUE_DELIMITER); + return data; + } +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetContentProvider.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetContentProvider.java new file mode 100644 index 00000000..9e6214b6 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetContentProvider.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.Viewer; + +public class PresetContentProvider implements IStructuredContentProvider { + + private PresetsStore store; + + public Object[] getElements(Object inputElement) { + return store.getAllPresets().toArray(); + } + + public void dispose() { + store = null; + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + if(newInput instanceof PresetsStore) { + store = (PresetsStore)newInput; + } + } + +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetData.java new file mode 100644 index 00000000..623358ed --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetData.java @@ -0,0 +1,149 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +import java.util.StringTokenizer; +import java.util.UUID; + +public class PresetData { + + // Status + private int position = 0; + private boolean enabled = true; + + // Preset + private String id = UUID.randomUUID().toString(); + private String name = "Name"; + private PresetType type = PresetType.presetTypeOpen; + private String command = "command"; + private OS os = OS.osWindows; + + public PresetData(OS os, String name, PresetType type, String command) { + this.os = os; + this.name = name; + this.type = type; + this.command = command; + } + + public PresetData() { + } + + public int getPosition() { + return position; + } + + public boolean isEnabled() { + return enabled; + } + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public PresetType getType() { + return type; + } + + public String getValue() { + return command; + } + + public OS getOs() { + return os; + } + + public void setPosition(int position) { + this.position = position; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public void setId(String id) { + this.id = id; + } + + public void setName(String name) { + this.name = name; + } + + public void setType(PresetType type) { + this.type = type; + } + + public void setValue(String value) { + this.command = value; + } + + public void setOs(OS os) { + this.os = os; + } + + public boolean equals(Object object) { + if(!(object instanceof PresetData)) { + return false; + } + PresetData data = (PresetData)object; + if(data.getPosition() == this.getPosition() & + data.getId().equals(this.getId()) & + data.getName().equals(this.getName()) & + data.getType() == this.getType() & + data.getValue().equals(this.getValue()) & + data.getOs().equals(this.getOs()) + ) + { + return true; + } + return false; + } + + public boolean fillTokens(String value, String delimiter) { + if(value == null || value.length() <= 0) { + return false; + } + StringTokenizer tokenizer = new StringTokenizer(value,delimiter); + String positionStr = tokenizer.nextToken(); + String enabledStr = tokenizer.nextToken(); + String idStr = tokenizer.nextToken(); + String nameStr = tokenizer.nextToken(); + String typeStr = tokenizer.nextToken(); + String valueStr = tokenizer.nextToken(); + String osStr = tokenizer.nextToken(); + // set members + setPosition(Integer.parseInt(positionStr)); + setEnabled(Boolean.valueOf(enabledStr).booleanValue()); + setId(idStr); + setName(nameStr); + setType(PresetType.getFromName(typeStr)); + setValue(valueStr); + setOs(OS.getFromName(osStr)); + return true; + } + + public String getMenuName() { + return getType().getName() + ": " + getName(); + } + + public String getMenuIcon() { + return getType().getIcon(); + } + + public String getTypeAction() { + return getType().getAction(); + } + +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetDataDefaultCollection.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetDataDefaultCollection.java new file mode 100644 index 00000000..403ecea9 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetDataDefaultCollection.java @@ -0,0 +1,356 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class PresetDataDefaultCollection { + + private List list = new ArrayList(); + + static public List getAllPresetsStatic() { + return new PresetDataDefaultCollection().getAllPresets(); + } + + static public List getDefaultPresetsStatic() { + return new PresetDataDefaultCollection().getDefaultPresets(); + } + + PresetDataDefaultCollection() { + // Windows DOS-Shell + list.add(new PresetData(OS.osWindows, "DOS-Shell", PresetType.presetTypeOpen, + "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} cmd.exe /K")); + list.add(new PresetData(OS.osWindows, "DOS-Shell", PresetType.presetTypeRun, + "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} ${easyshell:resource_name}")); + // Windows Explorer + list.add(new PresetData(OS.osWindows, "Explorer", PresetType.presetTypeExplore, + "explorer.exe /select, ${easyshell:resource_loc}")); + // Windows PowerShell + list.add(new PresetData(OS.osWindows, "PowerShell", PresetType.presetTypeOpen, + "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} powershell.exe")); + list.add(new PresetData(OS.osWindows, "PowerShell", PresetType.presetTypeRun, + "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} powershell.exe -command ./''${easyshell:resource_name}''")); + // Windows Cygwin (Bash) + list.add(new PresetData(OS.osWindows, "Cygwin (Bash)", PresetType.presetTypeOpen, + "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Cygwin\\bin\\bash.exe\"")); + list.add(new PresetData(OS.osWindows, "Cygwin (Bash)", PresetType.presetTypeRun, + "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Cygwin\\bin\\bash.exe\" -c ./''${easyshell:resource_name}''")); + // Windows Console + list.add(new PresetData(OS.osWindows, "Console", PresetType.presetTypeOpen, + "console.exe -w \"${easyshell:project_name}\" -d ${easyshell:container_loc}")); + list.add(new PresetData(OS.osWindows, "Cygwin (Bash)", PresetType.presetTypeRun, + "console.exe -w \"${easyshell:project_name}\" -d ${easyshell:container_loc} -r \"/k\\\"${easyshell:resource_name}\\\"\"")); + // Windows Git-Bash + list.add(new PresetData(OS.osWindows, "Git-Bash", PresetType.presetTypeOpen, + "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Program Files (x86)\\Git\\bin\\bash.exe\" --login -i")); + list.add(new PresetData(OS.osWindows, "Cygwin (Bash)", PresetType.presetTypeRun, + "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Program Files (x86)\\Git\\bin\\bash.exe\" --login -i -c ./''${easyshell:resource_name}''")); + // Windows ConEmu + list.add(new PresetData(OS.osWindows, "ConEmu", PresetType.presetTypeOpen, + "ConEmu.exe /Title \"${easyshell:project_name}\" /Dir \"${easyshell:container_loc}\" /Single /cmd cmd")); + list.add(new PresetData(OS.osWindows, "Cygwin (Bash)", PresetType.presetTypeRun, + "ConEmu.exe /Title \"${easyshell:project_name}\" /Dir \"${easyshell:container_loc}\" /Single /cmd \"${easyshell:resource_name}\"")); + // Windows TotalCommander + list.add(new PresetData(OS.osWindows, "TotalCommander", PresetType.presetTypeExplore, + "totalcmd.exe /O /T ${easyshell:container_loc}")); + // Windows Clipboard + list.add(new PresetData(OS.osWindows, "Full path", PresetType.presetTypeClipboard, + "\"${easyshell:resource_loc}\"${easyshell:line_separator}")); + // Linux KDE Konsole + list.add(new PresetData(OS.osLinux, "KDE Konsole", PresetType.presetTypeOpen, + "konsole --workdir ${easyshell:container_loc}")); + list.add(new PresetData(OS.osLinux, "KDE Konsole", PresetType.presetTypeRun, + "konsole --workdir ${easyshell:container_loc} --noclose -e ${easyshell:resource_loc}")); + // Linux Konqueror + list.add(new PresetData(OS.osLinux, "Konqueror", PresetType.presetTypeExplore, + "konqueror file:\"${easyshell:resource_loc}\"")); + // Linux Gnome Terminal + list.add(new PresetData(OS.osLinux, "Gnome Terminal", PresetType.presetTypeOpen, + "gnome-terminal --working-directory=${easyshell:container_loc}")); + list.add(new PresetData(OS.osLinux, "Gnome Terminal", PresetType.presetTypeRun, + "gnome-terminal --working-directory=${easyshell:container_loc} --command=./''${easyshell:resource_name}''")); + // Linux Xfce Terminal + list.add(new PresetData(OS.osLinux, "Xfce Terminal", PresetType.presetTypeOpen, + "xfce4-terminal --working-directory=${easyshell:container_loc}")); + list.add(new PresetData(OS.osLinux, "Xfce Terminal", PresetType.presetTypeRun, + "xfce4-terminal --working-directory=${easyshell:container_loc} --command=./''${easyshell:resource_name}'' --hold")); + // Linux Nautilus + list.add(new PresetData(OS.osLinux, "Nautilus", PresetType.presetTypeExplore, + "nautilus ${easyshell:resource_loc}")); + // Linux Dolphin + list.add(new PresetData(OS.osLinux, "Dolphin", PresetType.presetTypeExplore, + "dolphin --select ${easyshell:resource_loc}")); + // Linux Nemo + list.add(new PresetData(OS.osLinux, "Nemo", PresetType.presetTypeExplore, + "nemo ${easyshell:resource_loc}")); + // Linux Thunar + list.add(new PresetData(OS.osLinux, "Thunar", PresetType.presetTypeExplore, + "thunar ${easyshell:resource_loc}")); + // Linux Clipboard + list.add(new PresetData(OS.osLinux, "Full path", PresetType.presetTypeClipboard, + "${easyshell:resource_loc}${easyshell:line_separator}")); + // MAC OS X Terminal + list.add(new PresetData(OS.osMacOSX, "Terminal", PresetType.presetTypeOpen, + "open -a Terminal ${easyshell:container_loc}")); + list.add(new PresetData(OS.osMacOSX, "Terminal", PresetType.presetTypeRun, + "open -a Terminal ${easyshell:container_loc}")); + // MAC OS X Finder + list.add(new PresetData(OS.osMacOSX, "Finder", PresetType.presetTypeExplore, + "open -R ${easyshell:resource_loc}")); + // MAC OS X Clipboard + list.add(new PresetData(OS.osMacOSX, "Full path", PresetType.presetTypeClipboard, + "${easyshell:resource_loc}${easyshell:line_separator}")); + } + + public List getAllPresets() { + return list; + } + + public List getDefaultPresets() { + List listAll = getAllPresets(); + List listOS = new ArrayList(); + List listDefault = new ArrayList(); + OS os = getOS(); + // now get all data by OS + listOS = getPresetData(listAll, os); + // now get by name + switch(os) + { + case osWindows: + listDefault.add(getPresetData(listOS, "DOS-Shell", PresetType.presetTypeOpen)); + listDefault.add(getPresetData(listOS, "DOS-Shell", PresetType.presetTypeRun)); + listDefault.add(getPresetData(listOS, "Explorer", PresetType.presetTypeExplore)); + break; + case osLinux: + // try to detect the desktop + LinuxDesktop desktop = detectLinuxDesktop(); + //Activator.getDefault().sysout(true, "Detected linux (Unix) desktop: >" + desktop.getName() + "<"); + switch (desktop) { + case desktopKde: listDefault.add(getPresetData(listOS, "KDE", PresetType.presetTypeOpen)); + listDefault.add(getPresetData(listOS, "KDE", PresetType.presetTypeRun)); + listDefault.add(getPresetData(listOS, "Dolphin", PresetType.presetTypeExplore)); + break; + case desktopCinnamon: listDefault.add(getPresetData(listOS, "Gnome", PresetType.presetTypeOpen)); + listDefault.add(getPresetData(listOS, "Gnome", PresetType.presetTypeRun)); + listDefault.add(getPresetData(listOS, "Nemo", PresetType.presetTypeExplore)); + break; + case desktopGnome: listDefault.add(getPresetData(listOS, "Gnome", PresetType.presetTypeOpen)); + listDefault.add(getPresetData(listOS, "Gnome", PresetType.presetTypeRun)); + listDefault.add(getPresetData(listOS, "Nautilus", PresetType.presetTypeExplore)); + break; + case desktopXfce: listDefault.add(getPresetData(listOS, "Xfce", PresetType.presetTypeOpen)); + listDefault.add(getPresetData(listOS, "Xfce", PresetType.presetTypeRun)); + listDefault.add(getPresetData(listOS, "Thunar", PresetType.presetTypeExplore)); + break; + default:; + } + // try to detect the default file browser + if (desktop != LinuxDesktop.desktopUnknown) { + String fileBrowser = detectLinuxDefaultFileBrowser(); + //Activator.getDefault().sysout(true, "Detected linux (Unix) default file browser: >" + fileBrowser + "<"); + } + break; + case osMacOSX: + listDefault.add(getPresetData(listOS, "Terminal", PresetType.presetTypeOpen)); + listDefault.add(getPresetData(listOS, "Terminal", PresetType.presetTypeRun)); + listDefault.add(getPresetData(listOS, "Finder", PresetType.presetTypeExplore)); + break; + } + // add clipboard + listDefault.add(getPresetData(listOS, ".*path", PresetType.presetTypeClipboard)); + return listDefault; + } + + private OS getOS() { + OS os = OS.osUnknown; + /* possible OS string: + AIX + Digital UNIX + FreeBSD + HP UX + Irix + Linux + Mac OS + Mac OS X + MPE/iX + Netware 4.11 + OS/2 + Solaris + Windows 95 + Windows 98 + Windows NT + Windows Me + Windows 2000 + Windows XP + Windows 2003 + Windows CE + Windows Vista + Windows 7 + */ + String osname = System.getProperty("os.name", "").toLowerCase(); + if (osname.indexOf("windows") != -1) { + os = OS.osWindows; + } else if (osname.indexOf("mac os x") != -1) { + os = OS.osMacOSX; + } else if ( + osname.indexOf("unix") != -1 + || osname.indexOf("irix") != -1 + || osname.indexOf("freebsd") != -1 + || osname.indexOf("hp-ux") != -1 + || osname.indexOf("aix") != -1 + || osname.indexOf("sunos") != -1 + || osname.indexOf("linux") != -1 + ) + { + os = OS.osLinux; + } + return os; + } + + private static List getPresetData(List list, OS os) { + List listOut = new ArrayList(); + for (PresetData entry : list) { + if (entry.getOs() == os) { + listOut.add(entry); + } + } + return listOut; + } + + private static PresetData getPresetData(List list, String name, PresetType type) { + for (PresetData entry : list) { + if (entry.getType() == type && entry.getName().matches(name)) { + return entry; + } + } + return null; + } + + private static LinuxDesktop detectLinuxDesktop() { + LinuxDesktop resultCode = detectDesktopSession(); + /* + if (resultCode == LinuxDesktop.desktopUnknown) + { + if (isCde()) + resultCode = LinuxDesktop.desktopCde; + } + */ + return resultCode; + } + + /** + * detects desktop from $DESKTOP_SESSION + */ + private static LinuxDesktop detectDesktopSession() { + ArrayList command = new ArrayList(); + command.add("sh"); + command.add("-c"); + command.add("echo \"$DESKTOP_SESSION\""); + // fill the map + Map desktops = new HashMap(); + desktops.put("kde", LinuxDesktop.desktopKde); + desktops.put("gnome", LinuxDesktop.desktopGnome); + desktops.put("cinnamon", LinuxDesktop.desktopCinnamon); + desktops.put("xfce", LinuxDesktop.desktopXfce); + // execute + String desktop = isExpectedCommandOutput(command, desktops, true); + if (desktop != null && !desktop.isEmpty()) { + return (LinuxDesktop)desktops.get(desktop); + } + return LinuxDesktop.desktopUnknown; + } + + /** + * detects programs from $DESKTOP_SESSION + */ + private static String detectLinuxDefaultFileBrowser() { + ArrayList command = new ArrayList(); + command.add("xdg-mime"); + command.add("query"); + command.add("default"); + command.add("inode/directory"); + // fill the map + Map fileBrowsers = new HashMap(); + fileBrowsers.put("nemo.desktop", "nemo"); + // execute + String fileBrowser = isExpectedCommandOutput(command, fileBrowsers, true); + if (fileBrowser != null && !fileBrowser.isEmpty()) { + return (String)fileBrowsers.get(fileBrowser); + } + return null; + } + + /** + * Detects which desktop is used on a unix / linux system. + * + * @todo use regex + * + * @return The type of desktop. + * @see detectDesktop + */ + private static String isExpectedCommandOutput(ArrayList command, Map expectedOutput, boolean toLowerCase) { + boolean found = false; + String expectedLine = null; + try { + Process proc = Runtime.getRuntime().exec(command.toArray(new String[1])); + BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream())); + String line = null; + while((line = in.readLine()) != null && !found) { + for(String key: expectedOutput.keySet()) { + // in case of * just something should be returned + if (key.indexOf("*") != -1) + { + if (line.isEmpty()) { + found = false; + break; + } else { + found = true; + } + } else { + if (toLowerCase) + line = line.toLowerCase(); + if(line.indexOf(key) != -1) { + found = true; + } + } + if (found) { + expectedLine = line; + break; + } + } + } + line = null; + BufferedReader err = new BufferedReader(new InputStreamReader(proc.getErrorStream())); + // If there is any error output, print it to + // stdout for debugging purposes + while((line = err.readLine()) != null) { + //Activator.getDefault().sysout(true, "detectDesktop stderr >" + line + "<"); + } + + int result = proc.waitFor(); + if(result != 0) { + // If there is any error code, print it to + // stdout for debugging purposes + //Activator.getDefault().sysout(true, "detectDesktop return code: " + result); + } + } catch(Exception e) { + e.printStackTrace(); + } + return expectedLine; + } + +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetDialog.java new file mode 100644 index 00000000..7d9100a4 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetDialog.java @@ -0,0 +1,222 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +import java.util.List; + +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.dialogs.StatusDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CCombo; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +import de.anbos.eclipse.easyshell.plugin.Activator; + +public class PresetDialog extends StatusDialog { + + private PresetData data; + private boolean edit; + + private Button enabledCheckBox; + private Text nameText; + private CCombo typeCombo; + private Text valueText; + + public PresetDialog(Shell parent, PresetData data, boolean edit) { + super(parent); + this.data = data; + this.edit = edit; + // do layout and title + setShellStyle(getShellStyle() | SWT.MAX); + // set title + String title = null; + if(edit) { + title = Activator.getResourceString("easyshell.preseteditor.dialog.edit.title"); //$NON-NLS-1$ + } else { + title = Activator.getResourceString("easyshell.preseteditor.dialog.new.title"); //$NON-NLS-1$ + } + setTitle(title); + } + + public Control createDialogArea(Composite parent) { + Composite pageComponent = new Composite(parent,SWT.NULL); + GridLayout layout0 = new GridLayout(); + layout0.numColumns = 1; + layout0.makeColumnsEqualWidth = false; + layout0.marginWidth = 5; + layout0.marginHeight = 4; + pageComponent.setLayout(layout0); + GridData data0 = new GridData(GridData.FILL_HORIZONTAL); + pageComponent.setLayoutData(data0); + pageComponent.setFont(parent.getFont()); + // define group1 + Group pageGroup1 = new Group(pageComponent, SWT.SHADOW_ETCHED_IN); + pageGroup1.setText(Activator.getResourceString("easyshell.preseteditor.dialog.title")); + GridLayout layout1 = new GridLayout(); + layout1.numColumns = 2; + layout1.makeColumnsEqualWidth = false; + layout1.marginWidth = 5; + layout1.marginHeight = 4; + pageGroup1.setLayout(layout1); + GridData data1 = new GridData(GridData.FILL_HORIZONTAL); + pageGroup1.setLayoutData(data1); + pageGroup1.setFont(parent.getFont()); + // create activity checkbox + createEnabledCheckBox(pageGroup1); + // create rule type combo + createTypeCombo(pageGroup1); + //create input nameText field + nameText = createTextField(pageGroup1, Activator.getResourceString("easyshell.preseteditor.dialog.name.label"), data.getName()); + // create input valueText field + valueText = createTextField(pageGroup1, Activator.getResourceString("easyshell.preseteditor.dialog.value.label"), data.getValue()); + + //if (edit) { + // send event to refresh matchMode + Event event = new Event(); + event.item = null; + typeCombo.notifyListeners(SWT.Selection, event); + //} + + return pageComponent; + } + + protected void okPressed() { + int position = -1; + + boolean rulesOK = validateRuleValues(); + if (!rulesOK) { + return; + } + data.setPosition(position); + data.setEnabled(enabledCheckBox.getSelection()); + data.setType(PresetType.getFromName(typeCombo.getText())); + data.setName(nameText.getText()); + data.setValue(valueText.getText()); + super.okPressed(); + } + + private boolean validateRuleValues() { + + final String title = Activator.getResourceString("easyshell.preseteditor.dialog.error.incompletedata.title"); + + // check type + if ( (typeCombo.getText() == null) || (typeCombo.getText().length() <= 0)) { + MessageDialog.openError(getShell(), title, Activator.getResourceString("easyshell.preseteditor.dialog.error.type.text")); + return false; + } + + boolean valid = true; + + // check name + String text = Activator.getResourceString("easyshell.preseteditor.dialog.error.name.text"); + if ( (nameText.getText() == null) || (nameText.getText().length() <= 0)) { + valid = false; + } + + // check value + if (valid) { + text = Activator.getResourceString("easyshell.preseteditor.dialog.error.value.text"); + if ( (valueText.getText() == null) || (valueText.getText().length() <= 0)) { + valid = false; + } + } + + // show error message + if (!valid) { + MessageDialog.openError(getShell(), title, text); + } + return valid; + } + + private void createEnabledCheckBox(Composite parent) { + // draw label + Label comboLabel = new Label(parent,SWT.LEFT); + comboLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END)); + comboLabel.setText(Activator.getResourceString("easyshell.preseteditor.dialog.active.label")); //$NON-NLS-1$ + // draw checkbox + enabledCheckBox = new Button(parent,SWT.CHECK); + if(edit) { + enabledCheckBox.setSelection(this.data.isEnabled()); + } else { + enabledCheckBox.setSelection(true); + } + } + + private String[] getAllPresetTypesAsComboNames() { + List list = PresetType.getNamesAsList(); + String[] arr = new String[list.size()]; + for (int i=0;i getNamesAsList() { + List list = new ArrayList(); + for(int i = 0; i < PresetType.values().length; i++) { + if (PresetType.values()[i] != presetTypeUnknown) { + list.add(PresetType.values()[i].getName()); + } + } + return list; + } +} \ No newline at end of file diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetsPage.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetsPage.java new file mode 100644 index 00000000..5c7aed74 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetsPage.java @@ -0,0 +1,398 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +import java.util.Iterator; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.viewers.CheckStateChangedEvent; +import org.eclipse.jface.viewers.CheckboxTableViewer; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.ICheckStateListener; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerSorter; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ControlAdapter; +import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; + +import de.anbos.eclipse.easyshell.plugin.Activator; + +public class PresetsPage extends org.eclipse.jface.preference.PreferencePage + implements IWorkbenchPreferencePage { + + private static final int TABLE_WIDTH = 400; + + private Table table; + private ItemMover itemMover; + private PresetsStore store; + private CheckboxTableViewer tableViewer; + private Button addButton; + private Button editButton; + private Button upButton; + private Button downButton; + private Button removeButton; + + public void init(IWorkbench workbench) { + } + + public boolean performOk() { + store.save(); + return true; + } + + public void performDefaults() { + store.loadDefault(); + tableViewer.refresh(); + } + + protected void performApply() { + performOk(); + } + + protected Control createContents(Composite parent) { + Font font = parent.getFont(); + // define default grid + Composite pageComponent = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + layout.marginWidth = 0; + layout.marginHeight = 0; + pageComponent.setLayout(layout); + + // list + GridData data = new GridData(GridData.FILL_BOTH); + // create table + table = new Table(pageComponent, SWT.MULTI | SWT.CHECK | SWT.FULL_SELECTION); + table.setHeaderVisible(true); + table.setLinesVisible(true); + table.setFont(parent.getFont()); + + TableColumn column1 = new TableColumn(table, SWT.LEFT); + column1.setText(Activator.getResourceString("easyshell.preseteditor.table.header.column0.title")); //$NON-NLS-1$ + column1.setResizable(false); + + TableColumn column2 = new TableColumn(table, SWT.LEFT); + column2.setText(Activator.getResourceString("easyshell.preseteditor.table.header.column1.title")); //$NON-NLS-1$ + column2.setResizable(false); + + int availableRows = availableRows(pageComponent); + data.heightHint = table.getItemHeight() * (availableRows / 8); + data.widthHint = TABLE_WIDTH; + table.setLayoutData(data); + + tableViewer = new CheckboxTableViewer(table); + tableViewer.setLabelProvider(new PresetLabelProvider()); + tableViewer.setContentProvider(new PresetContentProvider()); + store = new PresetsStore(Activator.getDefault().getPreferenceStore()); + store.load(); + tableViewer.setInput(store); + tableViewer.setAllChecked(false); + tableViewer.setCheckedElements(store.getAllEnabledPresets()); + + tableViewer.addDoubleClickListener(new IDoubleClickListener() { + @Override + public void doubleClick(DoubleClickEvent event) { + edit(); + } + }); + + tableViewer.addCheckStateListener(new ICheckStateListener() { + @Override + public void checkStateChanged(CheckStateChangedEvent event) { + PresetData data = (PresetData) event.getElement(); + data.setEnabled(event.getChecked()); + } + }); + + tableViewer.addSelectionChangedListener(new ISelectionChangedListener() { + @Override + public void selectionChanged(SelectionChangedEvent event) { + IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection(); + boolean selected = !selection.isEmpty(); + editButton.setEnabled(selected); + removeButton.setEnabled(selected); + upButton.setEnabled(selected); + downButton.setEnabled(selected); + } + }); + + tableViewer.setSorter(new ViewerSorter() { + public int compare(Viewer viewer, Object object1, Object object2) { + if (!(object1 instanceof PresetData) || !(object2 instanceof PresetData)) { + return super.compare(viewer, object1, object2); + } + PresetData data1 = (PresetData) object1; + PresetData data2 = (PresetData) object2; + if (data1.getPosition() > data2.getPosition()) { + return 1; + } + if (data1.getPosition() < data2.getPosition()) { + return -1; + } + if (data1.getPosition() == data2.getPosition()) { + return 0; + } + return super.compare(viewer, object1, object2); + } + + public boolean isSorterProperty(Object element, String property) { + return true; + } + }); + + itemMover = new ItemMover(table, store); + + // button pageComponent + Composite groupComponent = new Composite(pageComponent, SWT.NULL); + GridLayout groupLayout = new GridLayout(); + groupLayout.marginWidth = 0; + groupLayout.marginHeight = 0; + groupComponent.setLayout(groupLayout); + data = new GridData(); + data.verticalAlignment = GridData.FILL; + data.horizontalAlignment = GridData.FILL; + groupComponent.setLayoutData(data); + groupComponent.setFont(font); + + // buttons + addButton = new Button(groupComponent, SWT.PUSH); + addButton.setText(Activator.getResourceString("easyshell.preseteditor.button.add")); //$NON-NLS-1$ + addButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + add(); + } + }); + addButton.setLayoutData(data); + addButton.setFont(font); + setButtonLayoutData(addButton); + + editButton = new Button(groupComponent, SWT.PUSH); + editButton.setText(Activator.getResourceString("easyshell.preseteditor.button.edit")); //$NON-NLS-1$ + editButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + edit(); + } + }); + editButton.setLayoutData(data); + editButton.setFont(font); + setButtonLayoutData(editButton); + + removeButton = new Button(groupComponent, SWT.PUSH); + removeButton.setText(Activator.getResourceString("easyshell.preseteditor.button.remove")); //$NON-NLS-1$ + removeButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + remove(); + } + }); + removeButton.setFont(font); + setButtonLayoutData(removeButton); + + upButton = new Button(groupComponent, SWT.PUSH); + upButton.setText(Activator.getResourceString("easyshell.preseteditor.button.up")); //$NON-NLS-1$ + upButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + up(); + } + }); + upButton.setFont(font); + setButtonLayoutData(upButton); + + downButton = new Button(groupComponent, SWT.PUSH); + downButton.setText(Activator.getResourceString("easyshell.preseteditor.button.down")); //$NON-NLS-1$ + downButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + down(); + } + }); + downButton.setFont(font); + setButtonLayoutData(downButton); + + configureTableResizing(table); + + Dialog.applyDialogFont(pageComponent); + // trigger the resize + table.getHorizontalBar().setVisible(true); + + // send event to refresh tableViewer + Event event = new Event(); + event.item = null; + table.pack(); + tableViewer.refresh(); + tableViewer.getTable().notifyListeners(SWT.Selection, event); + //tableViewer.getControl().setEnabled(true); + + return pageComponent; + } + + private int availableRows(Composite parent) { + int fontHeight = (parent.getFont().getFontData())[0].getHeight(); + int displayHeight = parent.getDisplay().getClientArea().height; + return displayHeight / fontHeight; + } + + /** + * Correctly resizes the table so no phantom columns appear + * + * @param table the table + * @since 3.1 + */ + private void configureTableResizing(final Table table) { + ControlAdapter resizer = new ControlAdapter() { + private boolean fIsResizing = false; + // private final int[] fWidths= {100, 70, 70, 130, 45}; + private final int[] fWidths = { 120, 280}; + private int fSum = TABLE_WIDTH; + + public void controlResized(ControlEvent e) { + if (fIsResizing) + return; + try { + fIsResizing = true; + int clientAreaWidth = table.getClientArea().width; + TableColumn[] columns = table.getColumns(); + int calculatedtableWidth = 0; + + if (e.widget == table) { + int initial[] = { 120, 280 }; + int minimums[] = new int[columns.length]; + int minSum = 0; + for (int i = 0; i < columns.length; i++) { + // don't make a column narrower than the minimum, + // or than what it is currently if less than the minimum + minimums[i] = Math.min(fWidths[i], initial[i]); + minSum += minimums[i]; + } + + int newWidth = fSum < clientAreaWidth ? clientAreaWidth : Math.max(clientAreaWidth, minSum); + final int toDistribute = newWidth - fSum; + int lastPart = toDistribute; + if (toDistribute != 0) { + int[] iteration = { 0, 1 }; // give the description column all the rest + for (int i = 0; i < iteration.length; i++) { + int c = iteration[i]; + int width; + if (fSum > 0) { + int part; + if (i == iteration.length - 1) + part = lastPart; + else + // current width is the weight for the distribution of the extra space + part = toDistribute * fWidths[c] / fSum; + lastPart -= part; + width = Math.max(minimums[c], fWidths[c] + part); + } else { + width = toDistribute * initial[c] / TABLE_WIDTH; + } + columns[c].setWidth(width); + fWidths[c] = width; + calculatedtableWidth += width; + } + fSum = calculatedtableWidth; + } + } else { + // column being resized + // on GTK, the last column gets auto-adapted - ignore this + if (e.widget == columns[2]) + return; + for (int i = 0; i < columns.length; i++) { + fWidths[i] = columns[i].getWidth(); + calculatedtableWidth += fWidths[i]; + } + fSum = calculatedtableWidth; + } + + // set scroll bar visible + table.getHorizontalBar().setVisible(calculatedtableWidth > clientAreaWidth); + } finally { + fIsResizing = false; + } + } + }; + table.addControlListener(resizer); + TableColumn[] columns = table.getColumns(); + for (int i = 0; i < columns.length; i++) { + columns[i].addControlListener(resizer); + } + } + + private void add() { + PresetData data = new PresetData(); + PresetDialog dialog = new PresetDialog(getShell(), data, false); + if (dialog.open() == Window.OK) { + store.add(data); + table.pack(); + tableViewer.refresh(); + tableViewer.setChecked(data, data.isEnabled()); + tableViewer.setSelection(new StructuredSelection(data)); + return; + } + } + + private void remove() { + IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection(); + Iterator elements = selection.iterator(); + while (elements.hasNext()) { + PresetData data = (PresetData) elements.next(); + store.delete(data); + } + table.pack(); + tableViewer.refresh(); + } + + private void edit() { + IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection(); + PresetData data = (PresetData) selection.getFirstElement(); + PresetDialog dialog = new PresetDialog(getShell(), data, true); + if (dialog.open() == Window.OK) { + table.pack(); + tableViewer.refresh(); + tableViewer.setChecked(data, data.isEnabled()); + tableViewer.setSelection(new StructuredSelection(data)); + return; + } + } + + private void up() { + itemMover.moveCurrentSelectionUp(); + tableViewer.refresh(); + } + + private void down() { + itemMover.moveCurrentSelectionDown(); + tableViewer.refresh(); + } + +} \ No newline at end of file diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetsStore.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetsStore.java new file mode 100644 index 00000000..af37fa05 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetsStore.java @@ -0,0 +1,172 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jface.preference.IPreferenceStore; + +public class PresetsStore { + + private IPreferenceStore store; + private List items; + private DataObjectComparator comparator; + + public PresetsStore(IPreferenceStore store) { + items = new ArrayList(); + this.store = store; + } + + public List getAllPresets() { + return items; + } + + public PresetData[] getAllEnabledPresets() { + List checkedItems = new ArrayList(); + Iterator dataIterator = items.iterator(); + while(dataIterator.hasNext()) { + PresetData data = (PresetData)dataIterator.next(); + if(data.isEnabled()) { + checkedItems.add(data); + } + } + if(checkedItems.size() <= 0) { + return new PresetData[0]; + } + PresetData[] checked = new PresetData[checkedItems.size()]; + for(int i = 0 ; i < checked.length ; i++) { + checked[i] = (PresetData)checkedItems.get(i); + } + return checked; + } + + public PresetData getPreviousElement(PresetData data) { + sort(); + for(int i = 0 ; i < items.size() ; i++) { + PresetData item = (PresetData)items.get(i); + if(item.equals(data)) { + try { + return (PresetData)items.get(i - 1); + } catch(Throwable t) { + return null; + } + } + } + return null; + } + + public PresetData getNextElement(PresetData data) { + sort(); + for(int i = 0 ; i < items.size() ; i++) { + PresetData item = (PresetData)items.get(i); + if(item.equals(data)) { + try { + return (PresetData)items.get(i + 1); + } catch(Throwable t) { + return null; + } + } + } + return null; + } + + public PresetData getLastElement() { + sort(); + int index = items.size() - 1; + if(index < 0) { + return null; + } + return (PresetData)items.get(index); + } + + public void add(PresetData data) { + int position = 0; + PresetData lastElement = getLastElement(); + if(lastElement != null) { + position = lastElement.getPosition() + 1; + } + data.setPosition(position); + items.add(data); + sort(); + } + + public void delete(PresetData data) { + items.remove(data); + sort(); + } + + public void save() { + store.setValue(Constants.PREF_PRESETS,PreferenceValueConverter.asString(getAllPresets())); + } + + public void loadDefault() { + PresetData[] items = PreferenceValueConverter.asPresetDataArray(store.getDefaultString(Constants.PREF_PRESETS)); + this.items.clear(); + for(int i = 0 ; i < items.length ; i++) { + this.items.add(items[i]); + } + sort(); + } + + public void load() { + PresetData[] items = PreferenceValueConverter.asPresetDataArray(store.getString(Constants.PREF_PRESETS)); + this.items.clear(); + for(int i = 0 ; i < items.length ; i++) { + this.items.add(items[i]); + } + sort(); + } + + public void removeAll() { + items.clear(); + } + + private void sort() { + if(comparator == null) { + comparator = new DataObjectComparator(); + } + Collections.sort(items,comparator); + for (int i=0;i { + public int compare(Object object1, Object object2) { + PresetData data1 = null; + PresetData data2 = null; + if(object1 instanceof PresetData) { + data1 = (PresetData)object1; + } + if(object2 instanceof PresetData) { + data2 = (PresetData)object2; + } + if(data1 == null | data2 == null) { + return -1; + } + if(data1.getPosition() > data2.getPosition()) { + return 1; + } + if(data1.getPosition() == data2.getPosition()) { + return 0; + } + if(data1.getPosition() < data2.getPosition()) { + return -1; + } + return -1; + } + } +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Quotes.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Quotes.java new file mode 100644 index 00000000..e7cb65ff --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Quotes.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2014 - 2016 by Andre Bossert + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +/** + * Quotes. + */ +public enum Quotes { + quotesNo(0, "No"), + quotesSingle(1, "Single"), + quotesDouble(2, "Double"), + quotesAuto(3, "Double (automatic)"), // check if no quotes and space in string, then add + quotesAutoSingle(4, "Single (automatic)"), // check if no quotes and space in string, then add + quotesEscape(5, "Escape"); // check if no quotes and space in string, then escape + // attributes + private final int id; + private final String mode; + // construct + Quotes(int id, String mode) { + this.id = id; + this.mode = mode; + } + public int getId() { + return id; + } + public String getMode() { + return mode; + } + public static Quotes getFromId(int id) { + Quotes ret = quotesNo; + for(int i = 0; i < Quotes.values().length; i++) { + if (Quotes.values()[i].getId() == id) { + ret = Quotes.values()[i]; + break; + } + } + return ret; + } +} \ No newline at end of file diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/SamplePreferencePage.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/SamplePreferencePage.java index 628deeb7..1c5640ff 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/SamplePreferencePage.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/SamplePreferencePage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015 Andre Bossert. + * Copyright (c) 2014 - 2016 Andre Bossert. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -47,6 +47,7 @@ public SamplePreferencePage() { * restore itself. */ public void createFieldEditors() { + /* addField(new DirectoryFieldEditor(PreferenceConstants.P_PATH, "&Directory preference:", getFieldEditorParent())); addField( @@ -64,6 +65,7 @@ public void createFieldEditors() { }, getFieldEditorParent())); addField( new StringFieldEditor(PreferenceConstants.P_STRING, "A &text preference:", getFieldEditorParent())); + */ } /* (non-Javadoc) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Tokenizer.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Tokenizer.java new file mode 100644 index 00000000..7f077a10 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Tokenizer.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +/** + * Tokenizer. + */ +public enum Tokenizer { + EasyShellTokenizerNo(0, "No"), + EasyShellTokenizerYes(1, "Yes"); + // attributes + private final int id; + private final String mode; + // construct + Tokenizer(int id, String mode) { + this.id = id; + this.mode = mode; + } + public int getId() { + return id; + } + public String getMode() { + return mode; + } + public static Tokenizer getFromId(int id) { + Tokenizer ret = EasyShellTokenizerYes; + for(int i = 0; i < Tokenizer.values().length; i++) { + if (Tokenizer.values()[i].getId() == id) { + ret = Tokenizer.values()[i]; + break; + } + } + return ret; + } +}; From 6aac78165ce49ddec00282e3a3ed97b23b3ba5f5 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Tue, 5 Jul 2016 20:27:55 +0200 Subject: [PATCH 02/73] #50 - [v2.0] issues found in early pre-release Adressed 1. There is a NPE if you create an item and then change its "type" to "Other" (and you click "OK") 2. Would be nice to list the new names to use as arguments since "{1}", "{2}", etc. don't work anymore. 3. Another small bug: when you click the "Edit" button for an item, its "type" is always reset to "Open". 4. Another small bug in this alpha version: when you edit an item, it doesn't keep its place, it is moved as the first item of the list. - fixed checked state after "Restore Defaults" - renamed preset to command - made dialog bigger and enable resizing Signed-off-by: Andre Bossert --- plugin/plugin.xml | 2 +- .../eclipse/easyshell/plugin/Activator.java | 9 +- .../easyshell/plugin/UIMessages.properties | 38 ++--- .../plugin/actions/ActionDelegate.java | 14 +- .../plugin/commands/DefineCommands.java | 19 +-- .../plugin/handlers/CommandHandler.java | 4 +- ...vider.java => CommandContentProvider.java} | 10 +- .../{PresetData.java => CommandData.java} | 18 +-- ...java => CommandDataDefaultCollection.java} | 134 +++++++++--------- .../{PresetDialog.java => CommandDialog.java} | 59 +++++--- ...rovider.java => CommandLabelProvider.java} | 10 +- .../plugin/preferences/CommandType.java | 105 ++++++++++++++ .../{PresetsPage.java => CommandsPage.java} | 62 ++++---- .../{PresetsStore.java => CommandsStore.java} | 91 +++++++----- .../plugin/preferences/Initializer.java | 2 +- .../plugin/preferences/ItemMover.java | 14 +- .../preferences/PreferenceValueConverter.java | 14 +- .../plugin/preferences/PresetType.java | 87 ------------ 18 files changed, 373 insertions(+), 319 deletions(-) rename plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/{PresetContentProvider.java => CommandContentProvider.java} (79%) rename plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/{PresetData.java => CommandData.java} (88%) rename plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/{PresetDataDefaultCollection.java => CommandDataDefaultCollection.java} (72%) rename plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/{PresetDialog.java => CommandDialog.java} (75%) rename plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/{PresetLabelProvider.java => CommandLabelProvider.java} (83%) create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandType.java rename plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/{PresetsPage.java => CommandsPage.java} (88%) rename plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/{PresetsStore.java => CommandsStore.java} (57%) delete mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetType.java diff --git a/plugin/plugin.xml b/plugin/plugin.xml index 23694d10..776e287a 100644 --- a/plugin/plugin.xml +++ b/plugin/plugin.xml @@ -60,7 +60,7 @@ diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java index 7ffc17ce..4c06e2ba 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java @@ -13,6 +13,7 @@ import java.net.URL; import java.text.MessageFormat; +import java.util.List; import java.util.MissingResourceException; import java.util.ResourceBundle; @@ -27,6 +28,7 @@ import org.osgi.framework.BundleContext; import de.anbos.eclipse.easyshell.plugin.preferences.Constants; +import de.anbos.eclipse.easyshell.plugin.preferences.CommandType; /** * The activator class controls the plug-in life cycle @@ -96,10 +98,9 @@ public static ImageDescriptor getImageDescriptor(String id) { } protected void initializeImageRegistry(ImageRegistry registry) { Bundle bundle = Platform.getBundle(Constants.PLUGIN_ID); - addImageToRegistry(registry, bundle, Constants.IMAGE_PATH + Constants.IMAGE_OPEN, Constants.IMAGE_OPEN); - addImageToRegistry(registry, bundle, Constants.IMAGE_PATH + Constants.IMAGE_RUN, Constants.IMAGE_RUN); - addImageToRegistry(registry, bundle, Constants.IMAGE_PATH + Constants.IMAGE_EXPLORE, Constants.IMAGE_EXPLORE); - addImageToRegistry(registry, bundle, Constants.IMAGE_PATH + Constants.IMAGE_CLIPBOARD, Constants.IMAGE_CLIPBOARD); + for (String icon : CommandType.getIconsAsList()) { + addImageToRegistry(registry, bundle, Constants.IMAGE_PATH + icon, icon); + } } protected void addImageToRegistry(ImageRegistry registry, Bundle bundle, String imagePath, String image_id) { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties index c84c11ac..a1ffbdc0 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties @@ -1,25 +1,25 @@ easyshell.plugin.name=EasyShell easyshell.properties.main.page.title=EasyShell -easyshell.properties.presets.page.title=Presets +easyshell.properties.commands.page.title=Presets easyshell.actionset.name=EasyShell -easyshell.preseteditor.table.header.column0.title=Name -easyshell.preseteditor.table.header.column1.title=Command -easyshell.preseteditor.button.add=Add... -easyshell.preseteditor.button.edit=Edit... -easyshell.preseteditor.button.remove=Remove -easyshell.preseteditor.button.up=Up -easyshell.preseteditor.button.down=Down +easyshell.command.editor.table.header.column0.title=Name +easyshell.command.editor.table.header.column1.title=Command +easyshell.command.editor.button.add=Add... +easyshell.command.editor.button.edit=Edit... +easyshell.command.editor.button.remove=Remove +easyshell.command.editor.button.up=Up +easyshell.command.editor.button.down=Down -easyshell.preseteditor.dialog.new.title=Create new preset -easyshell.preseteditor.dialog.edit.title=Edit existing preset -easyshell.preseteditor.dialog.title=Line selection +easyshell.command.editor.dialog.new.title=Create new command +easyshell.command.editor.dialog.edit.title=Edit existing command +easyshell.command.editor.dialog.title=Command definition -easyshell.preseteditor.dialog.error.incompletedata.title=Missing or Wrong command detected -easyshell.preseteditor.dialog.error.type.text=Please choose a type -easyshell.preseteditor.dialog.error.name.text=Please enter a valid name -easyshell.preseteditor.dialog.error.value.text=Please enter a valid command -easyshell.preseteditor.dialog.active.label=set active: -easyshell.preseteditor.dialog.combo.label=select type: -easyshell.preseteditor.dialog.name.label=enter name: -easyshell.preseteditor.dialog.value.label=enter command: \ No newline at end of file +easyshell.command.editor.dialog.error.incompletedata.title=Missing or wrong command detected +easyshell.command.editor.dialog.error.type.text=Please choose a type +easyshell.command.editor.dialog.error.name.text=Please enter a valid name +easyshell.command.editor.dialog.error.value.text=Please enter a valid command +easyshell.command.editor.dialog.active.label=enabled: +easyshell.command.editor.dialog.combo.label=type: +easyshell.command.editor.dialog.name.label=name: +easyshell.command.editor.dialog.value.label=command: \ No newline at end of file diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java index 0a3b960b..fd03b375 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java @@ -30,7 +30,7 @@ import de.anbos.eclipse.easyshell.plugin.DynamicVariableResolver; import de.anbos.eclipse.easyshell.plugin.Resource; import de.anbos.eclipse.easyshell.plugin.ResourceUtils; -import de.anbos.eclipse.easyshell.plugin.preferences.PresetType; +import de.anbos.eclipse.easyshell.plugin.preferences.CommandType; import de.anbos.eclipse.easyshell.plugin.preferences.Quotes; public class ActionDelegate implements IObjectActionDelegate { @@ -38,13 +38,13 @@ public class ActionDelegate implements IObjectActionDelegate { private Resource[] resource = null; private IStructuredSelection currentSelection; private String commandValue = null; - private PresetType commandType = PresetType.presetTypeUnknown; + private CommandType commandType = CommandType.commandTypeUnknown; - public PresetType getCommandType() { + public CommandType getCommandType() { return commandType; } - public void setCommandType(PresetType commandType) { + public void setCommandType(CommandType commandType) { this.commandType = commandType; } @@ -79,7 +79,7 @@ public void run(IAction action) { // String for all commands in case of clipboard String cmdAll = null; - if (commandType == PresetType.presetTypeClipboard) { + if (commandType == CommandType.commandTypeClipboard) { cmdAll = new String(); } @@ -133,7 +133,7 @@ public void run(IAction action) { // variable format DynamicVariableResolver.setArgs(args); // handling copy to clipboard - if (commandType == PresetType.presetTypeClipboard) { + if (commandType == CommandType.commandTypeClipboard) { String cmd = fixQuotes(variableManager.performStringSubstitution(target, false), quotes); //Activator.getDefault().sysout(true, "--- clp: >"); cmdAll += cmd; @@ -185,7 +185,7 @@ public void run(IAction action) { } // handling copy to clipboard - if ((commandType == PresetType.presetTypeClipboard) && (cmdAll != null) && (cmdAll.length() != 0)) { + if ((commandType == CommandType.commandTypeClipboard) && (cmdAll != null) && (cmdAll.length() != 0)) { Clipboard clipboard = new Clipboard(Display.getCurrent()); TextTransfer textTransfer = TextTransfer.getInstance(); Transfer[] transfers = new Transfer[]{textTransfer}; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java index 3d56d518..0c2202b5 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java @@ -12,6 +12,7 @@ package de.anbos.eclipse.easyshell.plugin.commands; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.eclipse.swt.SWT; @@ -22,8 +23,8 @@ import org.eclipse.ui.services.IServiceLocator; import de.anbos.eclipse.easyshell.plugin.Activator; -import de.anbos.eclipse.easyshell.plugin.preferences.PresetData; -import de.anbos.eclipse.easyshell.plugin.preferences.PresetsStore; +import de.anbos.eclipse.easyshell.plugin.preferences.CommandData; +import de.anbos.eclipse.easyshell.plugin.preferences.CommandsStore; public class DefineCommands extends ExtensionContributionFactory { @@ -35,18 +36,18 @@ public void createContributionItems(IServiceLocator serviceLocator, IContributionRoot additions) { // load the preferences - PresetsStore store = new PresetsStore(Activator.getDefault().getPreferenceStore()); + CommandsStore store = new CommandsStore(Activator.getDefault().getPreferenceStore()); store.load(); - PresetData[] items = store.getAllEnabledPresets(); - for (int i = 0; i < items.length; ++i) { + List items = store.getAllEnabledCommands(); + for (CommandData item : items) { addItem(serviceLocator, additions, - items[i].getMenuName(), + item.getMenuName(), "de.anbos.eclipse.easyshell.plugin.commands.execute", "de.anbos.eclipse.easyshell.plugin.commands.parameter.type", - items[i].getTypeAction(), + item.getTypeAction(), "de.anbos.eclipse.easyshell.plugin.commands.parameter.value", - items[i].getValue(), - items[i].getMenuIcon()); + item.getValue(), + item.getMenuIcon()); } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/CommandHandler.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/CommandHandler.java index 6f9c58ce..1f07f69d 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/CommandHandler.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/CommandHandler.java @@ -21,7 +21,7 @@ import de.anbos.eclipse.easyshell.plugin.EditorPropertyTester; import de.anbos.eclipse.easyshell.plugin.actions.Action; import de.anbos.eclipse.easyshell.plugin.actions.ActionDelegate; -import de.anbos.eclipse.easyshell.plugin.preferences.PresetType; +import de.anbos.eclipse.easyshell.plugin.preferences.CommandType; public class CommandHandler extends AbstractHandler { @@ -32,7 +32,7 @@ public Object execute(ExecutionEvent event) throws ExecutionException { String commandID = event.getCommand().getId(); String commandType = event.getParameter("de.anbos.eclipse.easyshell.plugin.commands.parameter.type"); String commanValue = event.getParameter("de.anbos.eclipse.easyshell.plugin.commands.parameter.value"); - action.setCommandType(PresetType.getFromAction(commandType)); + action.setCommandType(CommandType.getFromAction(commandType)); action.setCommandValue(commanValue); Action act = new Action(commandID); action.run((IAction)act); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetContentProvider.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandContentProvider.java similarity index 79% rename from plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetContentProvider.java rename to plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandContentProvider.java index 9e6214b6..e6006320 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetContentProvider.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandContentProvider.java @@ -14,12 +14,12 @@ import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.Viewer; -public class PresetContentProvider implements IStructuredContentProvider { +public class CommandContentProvider implements IStructuredContentProvider { - private PresetsStore store; + private CommandsStore store; public Object[] getElements(Object inputElement) { - return store.getAllPresets().toArray(); + return store.getAllCommandsArray(); } public void dispose() { @@ -27,8 +27,8 @@ public void dispose() { } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - if(newInput instanceof PresetsStore) { - store = (PresetsStore)newInput; + if(newInput instanceof CommandsStore) { + store = (CommandsStore)newInput; } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java similarity index 88% rename from plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetData.java rename to plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java index 623358ed..f771c643 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java @@ -14,7 +14,7 @@ import java.util.StringTokenizer; import java.util.UUID; -public class PresetData { +public class CommandData { // Status private int position = 0; @@ -23,18 +23,18 @@ public class PresetData { // Preset private String id = UUID.randomUUID().toString(); private String name = "Name"; - private PresetType type = PresetType.presetTypeOpen; + private CommandType type = CommandType.commandTypeOpen; private String command = "command"; private OS os = OS.osWindows; - public PresetData(OS os, String name, PresetType type, String command) { + public CommandData(OS os, String name, CommandType type, String command) { this.os = os; this.name = name; this.type = type; this.command = command; } - public PresetData() { + public CommandData() { } public int getPosition() { @@ -53,7 +53,7 @@ public String getName() { return name; } - public PresetType getType() { + public CommandType getType() { return type; } @@ -81,7 +81,7 @@ public void setName(String name) { this.name = name; } - public void setType(PresetType type) { + public void setType(CommandType type) { this.type = type; } @@ -94,10 +94,10 @@ public void setOs(OS os) { } public boolean equals(Object object) { - if(!(object instanceof PresetData)) { + if(!(object instanceof CommandData)) { return false; } - PresetData data = (PresetData)object; + CommandData data = (CommandData)object; if(data.getPosition() == this.getPosition() & data.getId().equals(this.getId()) & data.getName().equals(this.getName()) & @@ -128,7 +128,7 @@ public boolean fillTokens(String value, String delimiter) { setEnabled(Boolean.valueOf(enabledStr).booleanValue()); setId(idStr); setName(nameStr); - setType(PresetType.getFromName(typeStr)); + setType(CommandType.getFromName(typeStr)); setValue(valueStr); setOs(OS.getFromName(osStr)); return true; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetDataDefaultCollection.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java similarity index 72% rename from plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetDataDefaultCollection.java rename to plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java index 403ecea9..ad1ef57d 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetDataDefaultCollection.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java @@ -18,112 +18,112 @@ import java.util.List; import java.util.Map; -public class PresetDataDefaultCollection { +public class CommandDataDefaultCollection { - private List list = new ArrayList(); + private List list = new ArrayList(); - static public List getAllPresetsStatic() { - return new PresetDataDefaultCollection().getAllPresets(); + static public List getAllPresetsStatic() { + return new CommandDataDefaultCollection().getAllPresets(); } - static public List getDefaultPresetsStatic() { - return new PresetDataDefaultCollection().getDefaultPresets(); + static public List getDefaultPresetsStatic() { + return new CommandDataDefaultCollection().getDefaultPresets(); } - PresetDataDefaultCollection() { + CommandDataDefaultCollection() { // Windows DOS-Shell - list.add(new PresetData(OS.osWindows, "DOS-Shell", PresetType.presetTypeOpen, + list.add(new CommandData(OS.osWindows, "DOS-Shell", CommandType.commandTypeOpen, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} cmd.exe /K")); - list.add(new PresetData(OS.osWindows, "DOS-Shell", PresetType.presetTypeRun, + list.add(new CommandData(OS.osWindows, "DOS-Shell", CommandType.commandTypeRun, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} ${easyshell:resource_name}")); // Windows Explorer - list.add(new PresetData(OS.osWindows, "Explorer", PresetType.presetTypeExplore, + list.add(new CommandData(OS.osWindows, "Explorer", CommandType.commandTypeExplore, "explorer.exe /select, ${easyshell:resource_loc}")); // Windows PowerShell - list.add(new PresetData(OS.osWindows, "PowerShell", PresetType.presetTypeOpen, + list.add(new CommandData(OS.osWindows, "PowerShell", CommandType.commandTypeOpen, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} powershell.exe")); - list.add(new PresetData(OS.osWindows, "PowerShell", PresetType.presetTypeRun, + list.add(new CommandData(OS.osWindows, "PowerShell", CommandType.commandTypeRun, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} powershell.exe -command ./''${easyshell:resource_name}''")); // Windows Cygwin (Bash) - list.add(new PresetData(OS.osWindows, "Cygwin (Bash)", PresetType.presetTypeOpen, + list.add(new CommandData(OS.osWindows, "Cygwin (Bash)", CommandType.commandTypeOpen, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Cygwin\\bin\\bash.exe\"")); - list.add(new PresetData(OS.osWindows, "Cygwin (Bash)", PresetType.presetTypeRun, + list.add(new CommandData(OS.osWindows, "Cygwin (Bash)", CommandType.commandTypeRun, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Cygwin\\bin\\bash.exe\" -c ./''${easyshell:resource_name}''")); // Windows Console - list.add(new PresetData(OS.osWindows, "Console", PresetType.presetTypeOpen, + list.add(new CommandData(OS.osWindows, "Console", CommandType.commandTypeOpen, "console.exe -w \"${easyshell:project_name}\" -d ${easyshell:container_loc}")); - list.add(new PresetData(OS.osWindows, "Cygwin (Bash)", PresetType.presetTypeRun, + list.add(new CommandData(OS.osWindows, "Cygwin (Bash)", CommandType.commandTypeRun, "console.exe -w \"${easyshell:project_name}\" -d ${easyshell:container_loc} -r \"/k\\\"${easyshell:resource_name}\\\"\"")); // Windows Git-Bash - list.add(new PresetData(OS.osWindows, "Git-Bash", PresetType.presetTypeOpen, + list.add(new CommandData(OS.osWindows, "Git-Bash", CommandType.commandTypeOpen, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Program Files (x86)\\Git\\bin\\bash.exe\" --login -i")); - list.add(new PresetData(OS.osWindows, "Cygwin (Bash)", PresetType.presetTypeRun, + list.add(new CommandData(OS.osWindows, "Cygwin (Bash)", CommandType.commandTypeRun, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Program Files (x86)\\Git\\bin\\bash.exe\" --login -i -c ./''${easyshell:resource_name}''")); // Windows ConEmu - list.add(new PresetData(OS.osWindows, "ConEmu", PresetType.presetTypeOpen, + list.add(new CommandData(OS.osWindows, "ConEmu", CommandType.commandTypeOpen, "ConEmu.exe /Title \"${easyshell:project_name}\" /Dir \"${easyshell:container_loc}\" /Single /cmd cmd")); - list.add(new PresetData(OS.osWindows, "Cygwin (Bash)", PresetType.presetTypeRun, + list.add(new CommandData(OS.osWindows, "Cygwin (Bash)", CommandType.commandTypeRun, "ConEmu.exe /Title \"${easyshell:project_name}\" /Dir \"${easyshell:container_loc}\" /Single /cmd \"${easyshell:resource_name}\"")); // Windows TotalCommander - list.add(new PresetData(OS.osWindows, "TotalCommander", PresetType.presetTypeExplore, + list.add(new CommandData(OS.osWindows, "TotalCommander", CommandType.commandTypeExplore, "totalcmd.exe /O /T ${easyshell:container_loc}")); // Windows Clipboard - list.add(new PresetData(OS.osWindows, "Full path", PresetType.presetTypeClipboard, + list.add(new CommandData(OS.osWindows, "Full path", CommandType.commandTypeClipboard, "\"${easyshell:resource_loc}\"${easyshell:line_separator}")); // Linux KDE Konsole - list.add(new PresetData(OS.osLinux, "KDE Konsole", PresetType.presetTypeOpen, + list.add(new CommandData(OS.osLinux, "KDE Konsole", CommandType.commandTypeOpen, "konsole --workdir ${easyshell:container_loc}")); - list.add(new PresetData(OS.osLinux, "KDE Konsole", PresetType.presetTypeRun, + list.add(new CommandData(OS.osLinux, "KDE Konsole", CommandType.commandTypeRun, "konsole --workdir ${easyshell:container_loc} --noclose -e ${easyshell:resource_loc}")); // Linux Konqueror - list.add(new PresetData(OS.osLinux, "Konqueror", PresetType.presetTypeExplore, + list.add(new CommandData(OS.osLinux, "Konqueror", CommandType.commandTypeExplore, "konqueror file:\"${easyshell:resource_loc}\"")); // Linux Gnome Terminal - list.add(new PresetData(OS.osLinux, "Gnome Terminal", PresetType.presetTypeOpen, + list.add(new CommandData(OS.osLinux, "Gnome Terminal", CommandType.commandTypeOpen, "gnome-terminal --working-directory=${easyshell:container_loc}")); - list.add(new PresetData(OS.osLinux, "Gnome Terminal", PresetType.presetTypeRun, + list.add(new CommandData(OS.osLinux, "Gnome Terminal", CommandType.commandTypeRun, "gnome-terminal --working-directory=${easyshell:container_loc} --command=./''${easyshell:resource_name}''")); // Linux Xfce Terminal - list.add(new PresetData(OS.osLinux, "Xfce Terminal", PresetType.presetTypeOpen, + list.add(new CommandData(OS.osLinux, "Xfce Terminal", CommandType.commandTypeOpen, "xfce4-terminal --working-directory=${easyshell:container_loc}")); - list.add(new PresetData(OS.osLinux, "Xfce Terminal", PresetType.presetTypeRun, + list.add(new CommandData(OS.osLinux, "Xfce Terminal", CommandType.commandTypeRun, "xfce4-terminal --working-directory=${easyshell:container_loc} --command=./''${easyshell:resource_name}'' --hold")); // Linux Nautilus - list.add(new PresetData(OS.osLinux, "Nautilus", PresetType.presetTypeExplore, + list.add(new CommandData(OS.osLinux, "Nautilus", CommandType.commandTypeExplore, "nautilus ${easyshell:resource_loc}")); // Linux Dolphin - list.add(new PresetData(OS.osLinux, "Dolphin", PresetType.presetTypeExplore, + list.add(new CommandData(OS.osLinux, "Dolphin", CommandType.commandTypeExplore, "dolphin --select ${easyshell:resource_loc}")); // Linux Nemo - list.add(new PresetData(OS.osLinux, "Nemo", PresetType.presetTypeExplore, + list.add(new CommandData(OS.osLinux, "Nemo", CommandType.commandTypeExplore, "nemo ${easyshell:resource_loc}")); // Linux Thunar - list.add(new PresetData(OS.osLinux, "Thunar", PresetType.presetTypeExplore, + list.add(new CommandData(OS.osLinux, "Thunar", CommandType.commandTypeExplore, "thunar ${easyshell:resource_loc}")); // Linux Clipboard - list.add(new PresetData(OS.osLinux, "Full path", PresetType.presetTypeClipboard, + list.add(new CommandData(OS.osLinux, "Full path", CommandType.commandTypeClipboard, "${easyshell:resource_loc}${easyshell:line_separator}")); // MAC OS X Terminal - list.add(new PresetData(OS.osMacOSX, "Terminal", PresetType.presetTypeOpen, + list.add(new CommandData(OS.osMacOSX, "Terminal", CommandType.commandTypeOpen, "open -a Terminal ${easyshell:container_loc}")); - list.add(new PresetData(OS.osMacOSX, "Terminal", PresetType.presetTypeRun, + list.add(new CommandData(OS.osMacOSX, "Terminal", CommandType.commandTypeRun, "open -a Terminal ${easyshell:container_loc}")); // MAC OS X Finder - list.add(new PresetData(OS.osMacOSX, "Finder", PresetType.presetTypeExplore, + list.add(new CommandData(OS.osMacOSX, "Finder", CommandType.commandTypeExplore, "open -R ${easyshell:resource_loc}")); // MAC OS X Clipboard - list.add(new PresetData(OS.osMacOSX, "Full path", PresetType.presetTypeClipboard, + list.add(new CommandData(OS.osMacOSX, "Full path", CommandType.commandTypeClipboard, "${easyshell:resource_loc}${easyshell:line_separator}")); } - public List getAllPresets() { + public List getAllPresets() { return list; } - public List getDefaultPresets() { - List listAll = getAllPresets(); - List listOS = new ArrayList(); - List listDefault = new ArrayList(); + public List getDefaultPresets() { + List listAll = getAllPresets(); + List listOS = new ArrayList(); + List listDefault = new ArrayList(); OS os = getOS(); // now get all data by OS listOS = getPresetData(listAll, os); @@ -131,30 +131,30 @@ public List getDefaultPresets() { switch(os) { case osWindows: - listDefault.add(getPresetData(listOS, "DOS-Shell", PresetType.presetTypeOpen)); - listDefault.add(getPresetData(listOS, "DOS-Shell", PresetType.presetTypeRun)); - listDefault.add(getPresetData(listOS, "Explorer", PresetType.presetTypeExplore)); + listDefault.add(getPresetData(listOS, "DOS-Shell", CommandType.commandTypeOpen)); + listDefault.add(getPresetData(listOS, "DOS-Shell", CommandType.commandTypeRun)); + listDefault.add(getPresetData(listOS, "Explorer", CommandType.commandTypeExplore)); break; case osLinux: // try to detect the desktop LinuxDesktop desktop = detectLinuxDesktop(); //Activator.getDefault().sysout(true, "Detected linux (Unix) desktop: >" + desktop.getName() + "<"); switch (desktop) { - case desktopKde: listDefault.add(getPresetData(listOS, "KDE", PresetType.presetTypeOpen)); - listDefault.add(getPresetData(listOS, "KDE", PresetType.presetTypeRun)); - listDefault.add(getPresetData(listOS, "Dolphin", PresetType.presetTypeExplore)); + case desktopKde: listDefault.add(getPresetData(listOS, "KDE", CommandType.commandTypeOpen)); + listDefault.add(getPresetData(listOS, "KDE", CommandType.commandTypeRun)); + listDefault.add(getPresetData(listOS, "Dolphin", CommandType.commandTypeExplore)); break; - case desktopCinnamon: listDefault.add(getPresetData(listOS, "Gnome", PresetType.presetTypeOpen)); - listDefault.add(getPresetData(listOS, "Gnome", PresetType.presetTypeRun)); - listDefault.add(getPresetData(listOS, "Nemo", PresetType.presetTypeExplore)); + case desktopCinnamon: listDefault.add(getPresetData(listOS, "Gnome", CommandType.commandTypeOpen)); + listDefault.add(getPresetData(listOS, "Gnome", CommandType.commandTypeRun)); + listDefault.add(getPresetData(listOS, "Nemo", CommandType.commandTypeExplore)); break; - case desktopGnome: listDefault.add(getPresetData(listOS, "Gnome", PresetType.presetTypeOpen)); - listDefault.add(getPresetData(listOS, "Gnome", PresetType.presetTypeRun)); - listDefault.add(getPresetData(listOS, "Nautilus", PresetType.presetTypeExplore)); + case desktopGnome: listDefault.add(getPresetData(listOS, "Gnome", CommandType.commandTypeOpen)); + listDefault.add(getPresetData(listOS, "Gnome", CommandType.commandTypeRun)); + listDefault.add(getPresetData(listOS, "Nautilus", CommandType.commandTypeExplore)); break; - case desktopXfce: listDefault.add(getPresetData(listOS, "Xfce", PresetType.presetTypeOpen)); - listDefault.add(getPresetData(listOS, "Xfce", PresetType.presetTypeRun)); - listDefault.add(getPresetData(listOS, "Thunar", PresetType.presetTypeExplore)); + case desktopXfce: listDefault.add(getPresetData(listOS, "Xfce", CommandType.commandTypeOpen)); + listDefault.add(getPresetData(listOS, "Xfce", CommandType.commandTypeRun)); + listDefault.add(getPresetData(listOS, "Thunar", CommandType.commandTypeExplore)); break; default:; } @@ -165,13 +165,13 @@ public List getDefaultPresets() { } break; case osMacOSX: - listDefault.add(getPresetData(listOS, "Terminal", PresetType.presetTypeOpen)); - listDefault.add(getPresetData(listOS, "Terminal", PresetType.presetTypeRun)); - listDefault.add(getPresetData(listOS, "Finder", PresetType.presetTypeExplore)); + listDefault.add(getPresetData(listOS, "Terminal", CommandType.commandTypeOpen)); + listDefault.add(getPresetData(listOS, "Terminal", CommandType.commandTypeRun)); + listDefault.add(getPresetData(listOS, "Finder", CommandType.commandTypeExplore)); break; } // add clipboard - listDefault.add(getPresetData(listOS, ".*path", PresetType.presetTypeClipboard)); + listDefault.add(getPresetData(listOS, ".*path", CommandType.commandTypeClipboard)); return listDefault; } @@ -221,9 +221,9 @@ private OS getOS() { return os; } - private static List getPresetData(List list, OS os) { - List listOut = new ArrayList(); - for (PresetData entry : list) { + private static List getPresetData(List list, OS os) { + List listOut = new ArrayList(); + for (CommandData entry : list) { if (entry.getOs() == os) { listOut.add(entry); } @@ -231,8 +231,8 @@ private static List getPresetData(List list, OS os) { return listOut; } - private static PresetData getPresetData(List list, String name, PresetType type) { - for (PresetData entry : list) { + private static CommandData getPresetData(List list, String name, CommandType type) { + for (CommandData entry : list) { if (entry.getType() == type && entry.getName().matches(name)) { return entry; } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDialog.java similarity index 75% rename from plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetDialog.java rename to plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDialog.java index 7d9100a4..273a2f74 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDialog.java @@ -32,9 +32,9 @@ import de.anbos.eclipse.easyshell.plugin.Activator; -public class PresetDialog extends StatusDialog { +public class CommandDialog extends StatusDialog { - private PresetData data; + private CommandData data; private boolean edit; private Button enabledCheckBox; @@ -42,7 +42,7 @@ public class PresetDialog extends StatusDialog { private CCombo typeCombo; private Text valueText; - public PresetDialog(Shell parent, PresetData data, boolean edit) { + public CommandDialog(Shell parent, CommandData data, boolean edit) { super(parent); this.data = data; this.edit = edit; @@ -51,13 +51,18 @@ public PresetDialog(Shell parent, PresetData data, boolean edit) { // set title String title = null; if(edit) { - title = Activator.getResourceString("easyshell.preseteditor.dialog.edit.title"); //$NON-NLS-1$ + title = Activator.getResourceString("easyshell.command.editor.dialog.edit.title"); //$NON-NLS-1$ } else { - title = Activator.getResourceString("easyshell.preseteditor.dialog.new.title"); //$NON-NLS-1$ + title = Activator.getResourceString("easyshell.command.editor.dialog.new.title"); //$NON-NLS-1$ } setTitle(title); } + @Override + protected boolean isResizable() { + return true; + } + public Control createDialogArea(Composite parent) { Composite pageComponent = new Composite(parent,SWT.NULL); GridLayout layout0 = new GridLayout(); @@ -67,11 +72,12 @@ public Control createDialogArea(Composite parent) { layout0.marginHeight = 4; pageComponent.setLayout(layout0); GridData data0 = new GridData(GridData.FILL_HORIZONTAL); + data0.widthHint = 640; pageComponent.setLayoutData(data0); pageComponent.setFont(parent.getFont()); // define group1 Group pageGroup1 = new Group(pageComponent, SWT.SHADOW_ETCHED_IN); - pageGroup1.setText(Activator.getResourceString("easyshell.preseteditor.dialog.title")); + pageGroup1.setText(Activator.getResourceString("easyshell.command.editor.dialog.title")); GridLayout layout1 = new GridLayout(); layout1.numColumns = 2; layout1.makeColumnsEqualWidth = false; @@ -86,12 +92,26 @@ public Control createDialogArea(Composite parent) { // create rule type combo createTypeCombo(pageGroup1); //create input nameText field - nameText = createTextField(pageGroup1, Activator.getResourceString("easyshell.preseteditor.dialog.name.label"), data.getName()); + nameText = createTextField(pageGroup1, Activator.getResourceString("easyshell.command.editor.dialog.name.label"), data.getName()); // create input valueText field - valueText = createTextField(pageGroup1, Activator.getResourceString("easyshell.preseteditor.dialog.value.label"), data.getValue()); + valueText = createTextField(pageGroup1, Activator.getResourceString("easyshell.command.editor.dialog.value.label"), data.getValue()); + + // ------------------------------------ Description ------------------------------------------ + Label desc_label = new Label(pageComponent, 0); + desc_label.setText("${easyshell:drive} is the drive letter on Win32"); + desc_label = new Label(pageComponent, 0); + desc_label.setText("${easyshell:container_loc} is the parent path*"); + desc_label = new Label(pageComponent, 0); + desc_label.setText("${easyshell:resource_loc} is the full path*"); + desc_label = new Label(pageComponent, 0); + desc_label.setText("${easyshell:resource_name} is the file name*"); + desc_label = new Label(pageComponent, 0); + desc_label.setText("${easyshell:project_name} is the project name"); + desc_label = new Label(pageComponent, 0); + desc_label.setText("${easyshell:line_separator} is the line separator"); //if (edit) { - // send event to refresh matchMode + // send event to refresh Event event = new Event(); event.item = null; typeCombo.notifyListeners(SWT.Selection, event); @@ -101,15 +121,12 @@ public Control createDialogArea(Composite parent) { } protected void okPressed() { - int position = -1; - boolean rulesOK = validateRuleValues(); if (!rulesOK) { return; } - data.setPosition(position); data.setEnabled(enabledCheckBox.getSelection()); - data.setType(PresetType.getFromName(typeCombo.getText())); + data.setType(CommandType.getFromName(typeCombo.getText())); data.setName(nameText.getText()); data.setValue(valueText.getText()); super.okPressed(); @@ -117,25 +134,25 @@ protected void okPressed() { private boolean validateRuleValues() { - final String title = Activator.getResourceString("easyshell.preseteditor.dialog.error.incompletedata.title"); + final String title = Activator.getResourceString("easyshell.command.editor.dialog.error.incompletedata.title"); // check type if ( (typeCombo.getText() == null) || (typeCombo.getText().length() <= 0)) { - MessageDialog.openError(getShell(), title, Activator.getResourceString("easyshell.preseteditor.dialog.error.type.text")); + MessageDialog.openError(getShell(), title, Activator.getResourceString("easyshell.command.editor.dialog.error.type.text")); return false; } boolean valid = true; // check name - String text = Activator.getResourceString("easyshell.preseteditor.dialog.error.name.text"); + String text = Activator.getResourceString("easyshell.command.editor.dialog.error.name.text"); if ( (nameText.getText() == null) || (nameText.getText().length() <= 0)) { valid = false; } // check value if (valid) { - text = Activator.getResourceString("easyshell.preseteditor.dialog.error.value.text"); + text = Activator.getResourceString("easyshell.command.editor.dialog.error.value.text"); if ( (valueText.getText() == null) || (valueText.getText().length() <= 0)) { valid = false; } @@ -152,7 +169,7 @@ private void createEnabledCheckBox(Composite parent) { // draw label Label comboLabel = new Label(parent,SWT.LEFT); comboLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END)); - comboLabel.setText(Activator.getResourceString("easyshell.preseteditor.dialog.active.label")); //$NON-NLS-1$ + comboLabel.setText(Activator.getResourceString("easyshell.command.editor.dialog.active.label")); //$NON-NLS-1$ // draw checkbox enabledCheckBox = new Button(parent,SWT.CHECK); if(edit) { @@ -163,7 +180,7 @@ private void createEnabledCheckBox(Composite parent) { } private String[] getAllPresetTypesAsComboNames() { - List list = PresetType.getNamesAsList(); + List list = CommandType.getNamesAsList(); String[] arr = new String[list.size()]; for (int i=0;i getNamesAsList() { + List list = new ArrayList(); + for(int i = 0; i < CommandType.values().length; i++) { + if (CommandType.values()[i] != commandTypeUnknown) { + list.add(CommandType.values()[i].getName()); + } + } + return list; + } + public static List getIconsAsList() { + List list = new ArrayList(); + for(int i = 0; i < CommandType.values().length; i++) { + if (CommandType.values()[i] != commandTypeUnknown) { + list.add(CommandType.values()[i].getIcon()); + } + } + return list; + } + public static List getActionsAsList() { + List list = new ArrayList(); + for(int i = 0; i < CommandType.values().length; i++) { + if (CommandType.values()[i] != commandTypeUnknown) { + list.add(CommandType.values()[i].getAction()); + } + } + return list; + } +} \ No newline at end of file diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetsPage.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsPage.java similarity index 88% rename from plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetsPage.java rename to plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsPage.java index 5c7aed74..4d5e153d 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetsPage.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsPage.java @@ -45,14 +45,14 @@ import de.anbos.eclipse.easyshell.plugin.Activator; -public class PresetsPage extends org.eclipse.jface.preference.PreferencePage +public class CommandsPage extends org.eclipse.jface.preference.PreferencePage implements IWorkbenchPreferencePage { private static final int TABLE_WIDTH = 400; private Table table; private ItemMover itemMover; - private PresetsStore store; + private CommandsStore store; private CheckboxTableViewer tableViewer; private Button addButton; private Button editButton; @@ -60,23 +60,31 @@ public class PresetsPage extends org.eclipse.jface.preference.PreferencePage private Button downButton; private Button removeButton; + @Override public void init(IWorkbench workbench) { } + @Override public boolean performOk() { store.save(); return true; } - public void performDefaults() { - store.loadDefault(); - tableViewer.refresh(); + @Override + protected void performDefaults() { + store.loadDefaults(); + for (CommandData item : store.getAllEnabledCommands()) { + tableViewer.setChecked(item, true); + } + //tableViewer.refresh(); } + @Override protected void performApply() { performOk(); } + @Override protected Control createContents(Composite parent) { Font font = parent.getFont(); // define default grid @@ -96,11 +104,11 @@ protected Control createContents(Composite parent) { table.setFont(parent.getFont()); TableColumn column1 = new TableColumn(table, SWT.LEFT); - column1.setText(Activator.getResourceString("easyshell.preseteditor.table.header.column0.title")); //$NON-NLS-1$ + column1.setText(Activator.getResourceString("easyshell.command.editor.table.header.column0.title")); //$NON-NLS-1$ column1.setResizable(false); TableColumn column2 = new TableColumn(table, SWT.LEFT); - column2.setText(Activator.getResourceString("easyshell.preseteditor.table.header.column1.title")); //$NON-NLS-1$ + column2.setText(Activator.getResourceString("easyshell.command.editor.table.header.column1.title")); //$NON-NLS-1$ column2.setResizable(false); int availableRows = availableRows(pageComponent); @@ -109,13 +117,13 @@ protected Control createContents(Composite parent) { table.setLayoutData(data); tableViewer = new CheckboxTableViewer(table); - tableViewer.setLabelProvider(new PresetLabelProvider()); - tableViewer.setContentProvider(new PresetContentProvider()); - store = new PresetsStore(Activator.getDefault().getPreferenceStore()); + tableViewer.setLabelProvider(new CommandLabelProvider()); + tableViewer.setContentProvider(new CommandContentProvider()); + store = new CommandsStore(Activator.getDefault().getPreferenceStore()); store.load(); tableViewer.setInput(store); tableViewer.setAllChecked(false); - tableViewer.setCheckedElements(store.getAllEnabledPresets()); + tableViewer.setCheckedElements(store.getAllEnabledCommandsArray()); tableViewer.addDoubleClickListener(new IDoubleClickListener() { @Override @@ -127,7 +135,7 @@ public void doubleClick(DoubleClickEvent event) { tableViewer.addCheckStateListener(new ICheckStateListener() { @Override public void checkStateChanged(CheckStateChangedEvent event) { - PresetData data = (PresetData) event.getElement(); + CommandData data = (CommandData) event.getElement(); data.setEnabled(event.getChecked()); } }); @@ -146,11 +154,11 @@ public void selectionChanged(SelectionChangedEvent event) { tableViewer.setSorter(new ViewerSorter() { public int compare(Viewer viewer, Object object1, Object object2) { - if (!(object1 instanceof PresetData) || !(object2 instanceof PresetData)) { + if (!(object1 instanceof CommandData) || !(object2 instanceof CommandData)) { return super.compare(viewer, object1, object2); } - PresetData data1 = (PresetData) object1; - PresetData data2 = (PresetData) object2; + CommandData data1 = (CommandData) object1; + CommandData data2 = (CommandData) object2; if (data1.getPosition() > data2.getPosition()) { return 1; } @@ -184,7 +192,7 @@ public boolean isSorterProperty(Object element, String property) { // buttons addButton = new Button(groupComponent, SWT.PUSH); - addButton.setText(Activator.getResourceString("easyshell.preseteditor.button.add")); //$NON-NLS-1$ + addButton.setText(Activator.getResourceString("easyshell.command.editor.button.add")); //$NON-NLS-1$ addButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { @@ -196,7 +204,7 @@ public void widgetSelected(SelectionEvent event) { setButtonLayoutData(addButton); editButton = new Button(groupComponent, SWT.PUSH); - editButton.setText(Activator.getResourceString("easyshell.preseteditor.button.edit")); //$NON-NLS-1$ + editButton.setText(Activator.getResourceString("easyshell.command.editor.button.edit")); //$NON-NLS-1$ editButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { @@ -208,7 +216,7 @@ public void widgetSelected(SelectionEvent event) { setButtonLayoutData(editButton); removeButton = new Button(groupComponent, SWT.PUSH); - removeButton.setText(Activator.getResourceString("easyshell.preseteditor.button.remove")); //$NON-NLS-1$ + removeButton.setText(Activator.getResourceString("easyshell.command.editor.button.remove")); //$NON-NLS-1$ removeButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { @@ -219,7 +227,7 @@ public void widgetSelected(SelectionEvent event) { setButtonLayoutData(removeButton); upButton = new Button(groupComponent, SWT.PUSH); - upButton.setText(Activator.getResourceString("easyshell.preseteditor.button.up")); //$NON-NLS-1$ + upButton.setText(Activator.getResourceString("easyshell.command.editor.button.up")); //$NON-NLS-1$ upButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { @@ -230,7 +238,7 @@ public void widgetSelected(SelectionEvent event) { setButtonLayoutData(upButton); downButton = new Button(groupComponent, SWT.PUSH); - downButton.setText(Activator.getResourceString("easyshell.preseteditor.button.down")); //$NON-NLS-1$ + downButton.setText(Activator.getResourceString("easyshell.command.editor.button.down")); //$NON-NLS-1$ downButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { @@ -249,7 +257,6 @@ public void widgetSelected(SelectionEvent event) { // send event to refresh tableViewer Event event = new Event(); event.item = null; - table.pack(); tableViewer.refresh(); tableViewer.getTable().notifyListeners(SWT.Selection, event); //tableViewer.getControl().setEnabled(true); @@ -349,11 +356,10 @@ public void controlResized(ControlEvent e) { } private void add() { - PresetData data = new PresetData(); - PresetDialog dialog = new PresetDialog(getShell(), data, false); + CommandData data = new CommandData(); + CommandDialog dialog = new CommandDialog(getShell(), data, false); if (dialog.open() == Window.OK) { store.add(data); - table.pack(); tableViewer.refresh(); tableViewer.setChecked(data, data.isEnabled()); tableViewer.setSelection(new StructuredSelection(data)); @@ -365,19 +371,17 @@ private void remove() { IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection(); Iterator elements = selection.iterator(); while (elements.hasNext()) { - PresetData data = (PresetData) elements.next(); + CommandData data = (CommandData) elements.next(); store.delete(data); } - table.pack(); tableViewer.refresh(); } private void edit() { IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection(); - PresetData data = (PresetData) selection.getFirstElement(); - PresetDialog dialog = new PresetDialog(getShell(), data, true); + CommandData data = (CommandData) selection.getFirstElement(); + CommandDialog dialog = new CommandDialog(getShell(), data, true); if (dialog.open() == Window.OK) { - table.pack(); tableViewer.refresh(); tableViewer.setChecked(data, data.isEnabled()); tableViewer.setSelection(new StructuredSelection(data)); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetsStore.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsStore.java similarity index 57% rename from plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetsStore.java rename to plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsStore.java index af37fa05..e7110d57 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetsStore.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsStore.java @@ -19,47 +19,64 @@ import org.eclipse.jface.preference.IPreferenceStore; -public class PresetsStore { +public class CommandsStore { private IPreferenceStore store; - private List items; + private List items; private DataObjectComparator comparator; - public PresetsStore(IPreferenceStore store) { - items = new ArrayList(); + public CommandsStore(IPreferenceStore store) { + items = new ArrayList(); this.store = store; } - public List getAllPresets() { + public List getAllCommands() { return items; } - public PresetData[] getAllEnabledPresets() { - List checkedItems = new ArrayList(); - Iterator dataIterator = items.iterator(); + public CommandData[] getAllCommandsArray() { + List allItems = getAllCommands(); + if(allItems.size() <= 0) { + return new CommandData[0]; + } + CommandData[] allArray = new CommandData[allItems.size()]; + for(int i = 0 ; i < allArray.length ; i++) { + allArray[i] = (CommandData)allItems.get(i); + } + return allArray; + } + + public List getAllEnabledCommands() { + List checkedItems = new ArrayList(); + Iterator dataIterator = items.iterator(); while(dataIterator.hasNext()) { - PresetData data = (PresetData)dataIterator.next(); + CommandData data = (CommandData)dataIterator.next(); if(data.isEnabled()) { checkedItems.add(data); } } + return checkedItems; + } + + public CommandData[] getAllEnabledCommandsArray() { + List checkedItems = getAllEnabledCommands(); if(checkedItems.size() <= 0) { - return new PresetData[0]; + return new CommandData[0]; } - PresetData[] checked = new PresetData[checkedItems.size()]; + CommandData[] checked = new CommandData[checkedItems.size()]; for(int i = 0 ; i < checked.length ; i++) { - checked[i] = (PresetData)checkedItems.get(i); + checked[i] = (CommandData)checkedItems.get(i); } return checked; } - public PresetData getPreviousElement(PresetData data) { + public CommandData getPreviousElement(CommandData data) { sort(); for(int i = 0 ; i < items.size() ; i++) { - PresetData item = (PresetData)items.get(i); + CommandData item = (CommandData)items.get(i); if(item.equals(data)) { try { - return (PresetData)items.get(i - 1); + return (CommandData)items.get(i - 1); } catch(Throwable t) { return null; } @@ -68,13 +85,13 @@ public PresetData getPreviousElement(PresetData data) { return null; } - public PresetData getNextElement(PresetData data) { + public CommandData getNextElement(CommandData data) { sort(); for(int i = 0 ; i < items.size() ; i++) { - PresetData item = (PresetData)items.get(i); + CommandData item = (CommandData)items.get(i); if(item.equals(data)) { try { - return (PresetData)items.get(i + 1); + return (CommandData)items.get(i + 1); } catch(Throwable t) { return null; } @@ -83,18 +100,18 @@ public PresetData getNextElement(PresetData data) { return null; } - public PresetData getLastElement() { + public CommandData getLastElement() { sort(); int index = items.size() - 1; if(index < 0) { return null; } - return (PresetData)items.get(index); + return (CommandData)items.get(index); } - public void add(PresetData data) { + public void add(CommandData data) { int position = 0; - PresetData lastElement = getLastElement(); + CommandData lastElement = getLastElement(); if(lastElement != null) { position = lastElement.getPosition() + 1; } @@ -103,26 +120,22 @@ public void add(PresetData data) { sort(); } - public void delete(PresetData data) { + public void delete(CommandData data) { items.remove(data); sort(); } public void save() { - store.setValue(Constants.PREF_PRESETS,PreferenceValueConverter.asString(getAllPresets())); + store.setValue(Constants.PREF_PRESETS,PreferenceValueConverter.asString(getAllCommands())); } - public void loadDefault() { - PresetData[] items = PreferenceValueConverter.asPresetDataArray(store.getDefaultString(Constants.PREF_PRESETS)); - this.items.clear(); - for(int i = 0 ; i < items.length ; i++) { - this.items.add(items[i]); - } - sort(); + public void loadDefaults() { + store.setToDefault(Constants.PREF_PRESETS); + load(); } public void load() { - PresetData[] items = PreferenceValueConverter.asPresetDataArray(store.getString(Constants.PREF_PRESETS)); + CommandData[] items = PreferenceValueConverter.asPresetDataArray(store.getString(Constants.PREF_PRESETS)); this.items.clear(); for(int i = 0 ; i < items.length ; i++) { this.items.add(items[i]); @@ -140,19 +153,19 @@ private void sort() { } Collections.sort(items,comparator); for (int i=0;i { public int compare(Object object1, Object object2) { - PresetData data1 = null; - PresetData data2 = null; - if(object1 instanceof PresetData) { - data1 = (PresetData)object1; + CommandData data1 = null; + CommandData data2 = null; + if(object1 instanceof CommandData) { + data1 = (CommandData)object1; } - if(object2 instanceof PresetData) { - data2 = (PresetData)object2; + if(object2 instanceof CommandData) { + data2 = (CommandData)object2; } if(data1 == null | data2 == null) { return -1; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java index 84773d3f..be9ac540 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java @@ -20,7 +20,7 @@ public class Initializer extends AbstractPreferenceInitializer { public void initializeDefaultPreferences() { IPreferenceStore store = Activator.getDefault().getPreferenceStore(); - String defaultPresets = PreferenceValueConverter.asString(PresetDataDefaultCollection.getDefaultPresetsStatic()); + String defaultPresets = PreferenceValueConverter.asString(CommandDataDefaultCollection.getDefaultPresetsStatic()); store.setDefault(Constants.PREF_PRESETS,defaultPresets); //getDefaultPresets(); /* diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/ItemMover.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/ItemMover.java index 3589c6d6..4d12b416 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/ItemMover.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/ItemMover.java @@ -19,11 +19,11 @@ public class ItemMover implements SelectionListener { private Table table; - private PresetsStore store; + private CommandsStore store; - private PresetData currentSelection; + private CommandData currentSelection; - public ItemMover(Table table, PresetsStore store) { + public ItemMover(Table table, CommandsStore store) { this.table = table; this.store = store; table.addSelectionListener(this); @@ -33,7 +33,7 @@ public void moveCurrentSelectionUp() { if(currentSelection == null) { return; } - PresetData previousElement = store.getPreviousElement(currentSelection); + CommandData previousElement = store.getPreviousElement(currentSelection); if(previousElement == null) { return; } @@ -47,7 +47,7 @@ public void moveCurrentSelectionDown() { if(currentSelection == null) { return; } - PresetData nextElement = store.getNextElement(currentSelection); + CommandData nextElement = store.getNextElement(currentSelection); if(nextElement == null) { return; } @@ -68,10 +68,10 @@ public void widgetSelected(SelectionEvent e) { currentSelection = null; return; } - if(item == null || !(item.getData() instanceof PresetData)) { + if(item == null || !(item.getData() instanceof CommandData)) { currentSelection = null; return; } - currentSelection = (PresetData)item.getData(); + currentSelection = (CommandData)item.getData(); } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceValueConverter.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceValueConverter.java index fbd583ab..f5eec585 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceValueConverter.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceValueConverter.java @@ -26,16 +26,16 @@ public class PreferenceValueConverter { // Static ------------------------------------------------------------------ - public static String asString(List items) { + public static String asString(List items) { StringBuffer buffer = new StringBuffer(); - for(PresetData item : items) { + for(CommandData item : items) { buffer.append(asString(item)); buffer.append(ITEM_DELIMITER); } return buffer.toString(); } - public static final String asString(PresetData data) { + public static final String asString(CommandData data) { String position = Integer.toString(data.getPosition()); String enabled = Boolean.toString(data.isEnabled()); String id = data.getId(); @@ -57,17 +57,17 @@ public static final String asStringBase64(PresetData data) { } */ - public static PresetData[] asPresetDataArray(String value) { + public static CommandData[] asPresetDataArray(String value) { StringTokenizer tokenizer = new StringTokenizer(value,ITEM_DELIMITER); - PresetData[] items = new PresetData[tokenizer.countTokens()]; + CommandData[] items = new CommandData[tokenizer.countTokens()]; for(int i = 0 ; i < items.length ; i++) { items[i] = asPresetData(tokenizer.nextToken()); } return items; } - public static PresetData asPresetData(String value) { - PresetData data = new PresetData(); + public static CommandData asPresetData(String value) { + CommandData data = new CommandData(); data.fillTokens(value, VALUE_DELIMITER); return data; } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetType.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetType.java deleted file mode 100644 index a69808df..00000000 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetType.java +++ /dev/null @@ -1,87 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 - 2016 Andre Bossert. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Andre Bossert - initial API and implementation and/or initial documentation - *******************************************************************************/ - -package de.anbos.eclipse.easyshell.plugin.preferences; - -import java.util.ArrayList; -import java.util.List; - -public enum PresetType { - presetTypeUnknown(-1, "Unknown", Constants.IMAGE_UNKNOWN, Constants.ACTION_UNKNOWN), - presetTypeOpen(0, "Open", Constants.IMAGE_OPEN, Constants.ACTION_OPEN), - presetTypeRun(1, "Run", Constants.IMAGE_RUN, Constants.ACTION_RUN), - presetTypeExplore(2, "Explore", Constants.IMAGE_EXPLORE, Constants.ACTION_EXPLORE), - presetTypeClipboard(3, "Clipboard", Constants.IMAGE_CLIPBOARD, Constants.ACTION_CLIPBOARD), - presetTypeOther(4, "Other", Constants.IMAGE_OTHER, Constants.ACTION_OTHER); - // attributes - private final int id; - private final String name; - private final String icon; - private final String action; - // construct - PresetType(int id, String name, String icon, String action) { - this.id = id; - this.name = name; - this.icon = icon; - this.action = action; - } - public int getId() { - return id; - } - public String getName() { - return name; - } - public String getIcon() { - return icon; - } - public String getAction() { - return action; - } - public static PresetType getFromId(int id) { - PresetType ret = presetTypeUnknown; - for(int i = 0; i < PresetType.values().length; i++) { - if (PresetType.values()[i].getId() == id) { - ret = PresetType.values()[i]; - break; - } - } - return ret; - } - public static PresetType getFromName(String name) { - PresetType ret = presetTypeUnknown; - for(int i = 0; i < PresetType.values().length; i++) { - if (PresetType.values()[i].getName().equals(name)) { - ret = PresetType.values()[i]; - break; - } - } - return ret; - } - public static PresetType getFromAction(String action) { - PresetType ret = presetTypeUnknown; - for(int i = 0; i < PresetType.values().length; i++) { - if (PresetType.values()[i].getAction().equals(action)) { - ret = PresetType.values()[i]; - break; - } - } - return ret; - } - public static List getNamesAsList() { - List list = new ArrayList(); - for(int i = 0; i < PresetType.values().length; i++) { - if (PresetType.values()[i] != presetTypeUnknown) { - list.add(PresetType.values()[i].getName()); - } - } - return list; - } -} \ No newline at end of file From 4a051ef506d831a3b92a9591cddaafbe29290566 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Mon, 11 Jul 2016 22:18:14 +0200 Subject: [PATCH 03/73] [v2.0] split of menu and command preset definitions - changed store format - added resource type (file, folder and both) - show only presets for detected OS - configure default presets - removed CDE preset Signed-off-by: Andre Bossert --- .../easyshell/plugin/UIMessages.properties | 14 +- .../plugin/commands/DefineCommands.java | 18 +- .../plugin/preferences/CommandData.java | 124 +++++----- .../CommandDataDefaultCollection.java | 145 +++++++----- ...mandDialog.java => CommandDataDialog.java} | 42 +--- ...mmandsStore.java => CommandDataStore.java} | 127 +++++----- .../plugin/preferences/CommandMenuData.java | 119 ++++++++++ ...va => CommandMenuDataContentProvider.java} | 10 +- .../preferences/CommandMenuDataDialog.java | 224 ++++++++++++++++++ ...java => CommandMenuDataLabelProvider.java} | 14 +- ...emMover.java => CommandMenuDataMover.java} | 16 +- .../preferences/CommandMenuDataStore.java | 185 +++++++++++++++ .../plugin/preferences/CommandType.java | 10 + .../plugin/preferences/CommandsPage.java | 59 +++-- .../plugin/preferences/Constants.java | 5 +- .../easyshell/plugin/preferences/Debug.java | 33 ++- .../plugin/preferences/Initializer.java | 6 +- .../plugin/preferences/LinuxDesktop.java | 27 ++- .../easyshell/plugin/preferences/OS.java | 18 +- .../preferences/PreferenceValueConverter.java | 61 ++--- .../easyshell/plugin/preferences/Quotes.java | 33 ++- .../plugin/preferences/RessourceType.java | 75 ++++++ .../plugin/preferences/Tokenizer.java | 38 ++- 23 files changed, 1060 insertions(+), 343 deletions(-) rename plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/{CommandDialog.java => CommandDataDialog.java} (85%) rename plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/{CommandsStore.java => CommandDataStore.java} (58%) create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuData.java rename plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/{CommandContentProvider.java => CommandMenuDataContentProvider.java} (77%) create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuDataDialog.java rename plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/{CommandLabelProvider.java => CommandMenuDataLabelProvider.java} (76%) rename plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/{ItemMover.java => CommandMenuDataMover.java} (78%) create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuDataStore.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/RessourceType.java diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties index a1ffbdc0..436fe72c 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties @@ -19,7 +19,15 @@ easyshell.command.editor.dialog.error.incompletedata.title=Missing or wrong comm easyshell.command.editor.dialog.error.type.text=Please choose a type easyshell.command.editor.dialog.error.name.text=Please enter a valid name easyshell.command.editor.dialog.error.value.text=Please enter a valid command -easyshell.command.editor.dialog.active.label=enabled: -easyshell.command.editor.dialog.combo.label=type: easyshell.command.editor.dialog.name.label=name: -easyshell.command.editor.dialog.value.label=command: \ No newline at end of file +easyshell.command.editor.dialog.value.label=command: + +easyshell.menu.editor.dialog.new.title=Create new menu +easyshell.menu.editor.dialog.edit.title=Edit existing menu +easyshell.menu.editor.dialog.title=Menu definition +easyshell.menu.editor.dialog.active.label=enabled: +easyshell.menu.editor.dialog.name.label=menu name: +easyshell.menu.editor.dialog.combo.label=preset: +easyshell.menu.editor.dialog.command.label=command: + +easyshell.menu.editor.dialog.error.name.text=Please enter a valid name diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java index 0c2202b5..94e4844f 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java @@ -23,8 +23,8 @@ import org.eclipse.ui.services.IServiceLocator; import de.anbos.eclipse.easyshell.plugin.Activator; -import de.anbos.eclipse.easyshell.plugin.preferences.CommandData; -import de.anbos.eclipse.easyshell.plugin.preferences.CommandsStore; +import de.anbos.eclipse.easyshell.plugin.preferences.CommandMenuData; +import de.anbos.eclipse.easyshell.plugin.preferences.CommandMenuDataStore; public class DefineCommands extends ExtensionContributionFactory { @@ -36,18 +36,18 @@ public void createContributionItems(IServiceLocator serviceLocator, IContributionRoot additions) { // load the preferences - CommandsStore store = new CommandsStore(Activator.getDefault().getPreferenceStore()); + CommandMenuDataStore store = new CommandMenuDataStore(Activator.getDefault().getPreferenceStore()); store.load(); - List items = store.getAllEnabledCommands(); - for (CommandData item : items) { + List items = store.getEnabledCommandMenuDataList(); + for (CommandMenuData item : items) { addItem(serviceLocator, additions, - item.getMenuName(), + item.getName(), "de.anbos.eclipse.easyshell.plugin.commands.execute", "de.anbos.eclipse.easyshell.plugin.commands.parameter.type", - item.getTypeAction(), + item.getCommandData().getTypeAction(), "de.anbos.eclipse.easyshell.plugin.commands.parameter.value", - item.getValue(), - item.getMenuIcon()); + item.getCommandData().getCommand(), + item.getCommandData().getTypeIcon()); } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java index f771c643..61662244 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java @@ -16,34 +16,30 @@ public class CommandData { - // Status + // internal private int position = 0; - private boolean enabled = true; - - // Preset private String id = UUID.randomUUID().toString(); + // command + private OS os = OS.osWindows; private String name = "Name"; - private CommandType type = CommandType.commandTypeOpen; + private RessourceType resType = RessourceType.ressourceFileOrFolder; + private CommandType cmdType = CommandType.commandTypeOpen; private String command = "command"; - private OS os = OS.osWindows; - public CommandData(OS os, String name, CommandType type, String command) { + public CommandData(OS os, String name, RessourceType resType, CommandType cmdType, String command) { this.os = os; this.name = name; - this.type = type; + this.resType = resType; + this.cmdType = cmdType; this.command = command; } public CommandData() { } - public int getPosition() { - return position; - } - - public boolean isEnabled() { - return enabled; - } + public int getPosition() { + return position; + } public String getId() { return id; @@ -53,25 +49,25 @@ public String getName() { return name; } - public CommandType getType() { - return type; + public OS getOS() { + return os; } - public String getValue() { - return command; + public RessourceType getRessourceType() { + return resType; } - public OS getOs() { - return os; + public CommandType getCommandType() { + return cmdType; } - public void setPosition(int position) { - this.position = position; - } + public String getCommand() { + return command; + } - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } + public void setPosition(int position) { + this.position = position; + } public void setId(String id) { this.id = id; @@ -81,29 +77,34 @@ public void setName(String name) { this.name = name; } - public void setType(CommandType type) { - this.type = type; + public void setOs(OS os) { + this.os = os; } - public void setValue(String value) { - this.command = value; - } + public void setRessourceType(RessourceType resType) { + this.resType = resType; + } - public void setOs(OS os) { - this.os = os; + public void setCommandType(CommandType cmdType) { + this.cmdType = cmdType; } + public void setCommand(String command) { + this.command = command; + } + public boolean equals(Object object) { if(!(object instanceof CommandData)) { return false; } CommandData data = (CommandData)object; - if(data.getPosition() == this.getPosition() & - data.getId().equals(this.getId()) & - data.getName().equals(this.getName()) & - data.getType() == this.getType() & - data.getValue().equals(this.getValue()) & - data.getOs().equals(this.getOs()) + if(data.getPosition() == this.getPosition() && + data.getName().equals(this.getName()) && + data.getOS() == this.getOS() && + data.getRessourceType() == this.getRessourceType() && + data.getCommandType() == this.getCommandType() && + data.getCommand().equals(this.getCommand() + ) ) { return true; @@ -111,39 +112,34 @@ public boolean equals(Object object) { return false; } - public boolean fillTokens(String value, String delimiter) { - if(value == null || value.length() <= 0) { - return false; - } - StringTokenizer tokenizer = new StringTokenizer(value,delimiter); - String positionStr = tokenizer.nextToken(); - String enabledStr = tokenizer.nextToken(); - String idStr = tokenizer.nextToken(); - String nameStr = tokenizer.nextToken(); - String typeStr = tokenizer.nextToken(); - String valueStr = tokenizer.nextToken(); - String osStr = tokenizer.nextToken(); + public boolean deserialize(String value, StringTokenizer tokenizer, String delimiter) { + if((value == null || value.length() <= 0) && tokenizer == null) { + return false; + } + if (tokenizer == null) { + tokenizer = new StringTokenizer(value,delimiter); + } // set members - setPosition(Integer.parseInt(positionStr)); - setEnabled(Boolean.valueOf(enabledStr).booleanValue()); - setId(idStr); - setName(nameStr); - setType(CommandType.getFromName(typeStr)); - setValue(valueStr); - setOs(OS.getFromName(osStr)); + setPosition(Integer.parseInt(tokenizer.nextToken())); + setId(tokenizer.nextToken()); + setName(tokenizer.nextToken()); + setOs(OS.getFromEnum(tokenizer.nextToken())); + setRessourceType(RessourceType.getFromEnum(tokenizer.nextToken())); + setCommandType(CommandType.getFromEnum(tokenizer.nextToken())); + setCommand(tokenizer.nextToken()); return true; } - public String getMenuName() { - return getType().getName() + ": " + getName(); + public String serialize(String delimiter) { + return Integer.toString(getPosition()) + delimiter + getId() + delimiter + getName() + delimiter + getOS().toString() + delimiter + getRessourceType().toString() + delimiter + getCommandType().toString() + delimiter + getCommand() + delimiter; } - public String getMenuIcon() { - return getType().getIcon(); + public String getTypeIcon() { + return getCommandType().getIcon(); } public String getTypeAction() { - return getType().getAction(); + return getCommandType().getAction(); } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java index ad1ef57d..9b8bae10 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java @@ -21,140 +21,159 @@ public class CommandDataDefaultCollection { private List list = new ArrayList(); + private static CommandDataDefaultCollection instance = new CommandDataDefaultCollection(); - static public List getAllPresetsStatic() { - return new CommandDataDefaultCollection().getAllPresets(); + public static List getAllCommandsStatic() { + return instance.getCommands(); } - static public List getDefaultPresetsStatic() { - return new CommandDataDefaultCollection().getDefaultPresets(); + public static List getDefaultCommandsStatic() { + return getDefaultCommands(); + } + + public static List getDefaultCommandsMenuStatic() { + List list = getDefaultCommandsStatic(); + List ret = new ArrayList(); + for (CommandData data : list) { + ret.add(new CommandMenuData(data)); + } + return ret; } CommandDataDefaultCollection() { // Windows DOS-Shell - list.add(new CommandData(OS.osWindows, "DOS-Shell", CommandType.commandTypeOpen, + list.add(new CommandData(OS.osWindows, "DOS-Shell", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} cmd.exe /K")); - list.add(new CommandData(OS.osWindows, "DOS-Shell", CommandType.commandTypeRun, + list.add(new CommandData(OS.osWindows, "DOS-Shell", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} ${easyshell:resource_name}")); // Windows Explorer - list.add(new CommandData(OS.osWindows, "Explorer", CommandType.commandTypeExplore, + list.add(new CommandData(OS.osWindows, "Explorer", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, "explorer.exe /select, ${easyshell:resource_loc}")); // Windows PowerShell - list.add(new CommandData(OS.osWindows, "PowerShell", CommandType.commandTypeOpen, + list.add(new CommandData(OS.osWindows, "PowerShell", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} powershell.exe")); - list.add(new CommandData(OS.osWindows, "PowerShell", CommandType.commandTypeRun, + list.add(new CommandData(OS.osWindows, "PowerShell", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} powershell.exe -command ./''${easyshell:resource_name}''")); // Windows Cygwin (Bash) - list.add(new CommandData(OS.osWindows, "Cygwin (Bash)", CommandType.commandTypeOpen, + list.add(new CommandData(OS.osWindows, "Cygwin (Bash)", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Cygwin\\bin\\bash.exe\"")); - list.add(new CommandData(OS.osWindows, "Cygwin (Bash)", CommandType.commandTypeRun, + list.add(new CommandData(OS.osWindows, "Cygwin (Bash)", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Cygwin\\bin\\bash.exe\" -c ./''${easyshell:resource_name}''")); // Windows Console - list.add(new CommandData(OS.osWindows, "Console", CommandType.commandTypeOpen, + list.add(new CommandData(OS.osWindows, "Console", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, "console.exe -w \"${easyshell:project_name}\" -d ${easyshell:container_loc}")); - list.add(new CommandData(OS.osWindows, "Cygwin (Bash)", CommandType.commandTypeRun, + list.add(new CommandData(OS.osWindows, "Cygwin (Bash)", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, "console.exe -w \"${easyshell:project_name}\" -d ${easyshell:container_loc} -r \"/k\\\"${easyshell:resource_name}\\\"\"")); // Windows Git-Bash - list.add(new CommandData(OS.osWindows, "Git-Bash", CommandType.commandTypeOpen, + list.add(new CommandData(OS.osWindows, "Git-Bash", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Program Files (x86)\\Git\\bin\\bash.exe\" --login -i")); - list.add(new CommandData(OS.osWindows, "Cygwin (Bash)", CommandType.commandTypeRun, + list.add(new CommandData(OS.osWindows, "Cygwin (Bash)", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Program Files (x86)\\Git\\bin\\bash.exe\" --login -i -c ./''${easyshell:resource_name}''")); // Windows ConEmu - list.add(new CommandData(OS.osWindows, "ConEmu", CommandType.commandTypeOpen, + list.add(new CommandData(OS.osWindows, "ConEmu", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, "ConEmu.exe /Title \"${easyshell:project_name}\" /Dir \"${easyshell:container_loc}\" /Single /cmd cmd")); - list.add(new CommandData(OS.osWindows, "Cygwin (Bash)", CommandType.commandTypeRun, + list.add(new CommandData(OS.osWindows, "Cygwin (Bash)", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, "ConEmu.exe /Title \"${easyshell:project_name}\" /Dir \"${easyshell:container_loc}\" /Single /cmd \"${easyshell:resource_name}\"")); // Windows TotalCommander - list.add(new CommandData(OS.osWindows, "TotalCommander", CommandType.commandTypeExplore, + list.add(new CommandData(OS.osWindows, "TotalCommander", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, "totalcmd.exe /O /T ${easyshell:container_loc}")); // Windows Clipboard - list.add(new CommandData(OS.osWindows, "Full path", CommandType.commandTypeClipboard, + list.add(new CommandData(OS.osWindows, "Full path", RessourceType.ressourceFileOrFolder, CommandType.commandTypeClipboard, "\"${easyshell:resource_loc}\"${easyshell:line_separator}")); // Linux KDE Konsole - list.add(new CommandData(OS.osLinux, "KDE Konsole", CommandType.commandTypeOpen, + list.add(new CommandData(OS.osLinux, "KDE Konsole", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, "konsole --workdir ${easyshell:container_loc}")); - list.add(new CommandData(OS.osLinux, "KDE Konsole", CommandType.commandTypeRun, + list.add(new CommandData(OS.osLinux, "KDE Konsole", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, "konsole --workdir ${easyshell:container_loc} --noclose -e ${easyshell:resource_loc}")); // Linux Konqueror - list.add(new CommandData(OS.osLinux, "Konqueror", CommandType.commandTypeExplore, + list.add(new CommandData(OS.osLinux, "Konqueror", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, "konqueror file:\"${easyshell:resource_loc}\"")); // Linux Gnome Terminal - list.add(new CommandData(OS.osLinux, "Gnome Terminal", CommandType.commandTypeOpen, + list.add(new CommandData(OS.osLinux, "Gnome Terminal", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, "gnome-terminal --working-directory=${easyshell:container_loc}")); - list.add(new CommandData(OS.osLinux, "Gnome Terminal", CommandType.commandTypeRun, + list.add(new CommandData(OS.osLinux, "Gnome Terminal", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, "gnome-terminal --working-directory=${easyshell:container_loc} --command=./''${easyshell:resource_name}''")); // Linux Xfce Terminal - list.add(new CommandData(OS.osLinux, "Xfce Terminal", CommandType.commandTypeOpen, + list.add(new CommandData(OS.osLinux, "Xfce Terminal", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, "xfce4-terminal --working-directory=${easyshell:container_loc}")); - list.add(new CommandData(OS.osLinux, "Xfce Terminal", CommandType.commandTypeRun, + list.add(new CommandData(OS.osLinux, "Xfce Terminal", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, "xfce4-terminal --working-directory=${easyshell:container_loc} --command=./''${easyshell:resource_name}'' --hold")); // Linux Nautilus - list.add(new CommandData(OS.osLinux, "Nautilus", CommandType.commandTypeExplore, + list.add(new CommandData(OS.osLinux, "Nautilus", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, "nautilus ${easyshell:resource_loc}")); // Linux Dolphin - list.add(new CommandData(OS.osLinux, "Dolphin", CommandType.commandTypeExplore, + list.add(new CommandData(OS.osLinux, "Dolphin", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, "dolphin --select ${easyshell:resource_loc}")); // Linux Nemo - list.add(new CommandData(OS.osLinux, "Nemo", CommandType.commandTypeExplore, + list.add(new CommandData(OS.osLinux, "Nemo", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, "nemo ${easyshell:resource_loc}")); // Linux Thunar - list.add(new CommandData(OS.osLinux, "Thunar", CommandType.commandTypeExplore, + list.add(new CommandData(OS.osLinux, "Thunar", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, "thunar ${easyshell:resource_loc}")); // Linux Clipboard - list.add(new CommandData(OS.osLinux, "Full path", CommandType.commandTypeClipboard, + list.add(new CommandData(OS.osLinux, "Full path", RessourceType.ressourceFileOrFolder, CommandType.commandTypeClipboard, "${easyshell:resource_loc}${easyshell:line_separator}")); // MAC OS X Terminal - list.add(new CommandData(OS.osMacOSX, "Terminal", CommandType.commandTypeOpen, + list.add(new CommandData(OS.osMacOSX, "Terminal", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, "open -a Terminal ${easyshell:container_loc}")); - list.add(new CommandData(OS.osMacOSX, "Terminal", CommandType.commandTypeRun, + list.add(new CommandData(OS.osMacOSX, "Terminal", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, "open -a Terminal ${easyshell:container_loc}")); // MAC OS X Finder - list.add(new CommandData(OS.osMacOSX, "Finder", CommandType.commandTypeExplore, + list.add(new CommandData(OS.osMacOSX, "Finder", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, "open -R ${easyshell:resource_loc}")); // MAC OS X Clipboard - list.add(new CommandData(OS.osMacOSX, "Full path", CommandType.commandTypeClipboard, + list.add(new CommandData(OS.osMacOSX, "Full path", RessourceType.ressourceFileOrFolder, CommandType.commandTypeClipboard, "${easyshell:resource_loc}${easyshell:line_separator}")); } - public List getAllPresets() { + public List getCommands() { return list; } - public List getDefaultPresets() { - List listAll = getAllPresets(); + public static List getCommandsNative(List list) { + if (list == null) { + list = getAllCommandsStatic(); + } + return getCommandData(list, getOS()); + } + + public static List getDefaultCommands() { + List listAll = getAllCommandsStatic(); List listOS = new ArrayList(); List listDefault = new ArrayList(); OS os = getOS(); // now get all data by OS - listOS = getPresetData(listAll, os); + listOS = getCommandData(listAll, os); // now get by name switch(os) { + case osUnknown: + break; case osWindows: - listDefault.add(getPresetData(listOS, "DOS-Shell", CommandType.commandTypeOpen)); - listDefault.add(getPresetData(listOS, "DOS-Shell", CommandType.commandTypeRun)); - listDefault.add(getPresetData(listOS, "Explorer", CommandType.commandTypeExplore)); + listDefault.add(getCommandData(listOS, "DOS-Shell", CommandType.commandTypeOpen)); + listDefault.add(getCommandData(listOS, "DOS-Shell", CommandType.commandTypeRun)); + listDefault.add(getCommandData(listOS, "Explorer", CommandType.commandTypeExplore)); break; case osLinux: // try to detect the desktop LinuxDesktop desktop = detectLinuxDesktop(); //Activator.getDefault().sysout(true, "Detected linux (Unix) desktop: >" + desktop.getName() + "<"); switch (desktop) { - case desktopKde: listDefault.add(getPresetData(listOS, "KDE", CommandType.commandTypeOpen)); - listDefault.add(getPresetData(listOS, "KDE", CommandType.commandTypeRun)); - listDefault.add(getPresetData(listOS, "Dolphin", CommandType.commandTypeExplore)); + case desktopKde: listDefault.add(getCommandData(listOS, "KDE", CommandType.commandTypeOpen)); + listDefault.add(getCommandData(listOS, "KDE", CommandType.commandTypeRun)); + listDefault.add(getCommandData(listOS, "Dolphin", CommandType.commandTypeExplore)); break; - case desktopCinnamon: listDefault.add(getPresetData(listOS, "Gnome", CommandType.commandTypeOpen)); - listDefault.add(getPresetData(listOS, "Gnome", CommandType.commandTypeRun)); - listDefault.add(getPresetData(listOS, "Nemo", CommandType.commandTypeExplore)); + case desktopCinnamon: listDefault.add(getCommandData(listOS, "Gnome", CommandType.commandTypeOpen)); + listDefault.add(getCommandData(listOS, "Gnome", CommandType.commandTypeRun)); + listDefault.add(getCommandData(listOS, "Nemo", CommandType.commandTypeExplore)); break; - case desktopGnome: listDefault.add(getPresetData(listOS, "Gnome", CommandType.commandTypeOpen)); - listDefault.add(getPresetData(listOS, "Gnome", CommandType.commandTypeRun)); - listDefault.add(getPresetData(listOS, "Nautilus", CommandType.commandTypeExplore)); + case desktopGnome: listDefault.add(getCommandData(listOS, "Gnome", CommandType.commandTypeOpen)); + listDefault.add(getCommandData(listOS, "Gnome", CommandType.commandTypeRun)); + listDefault.add(getCommandData(listOS, "Nautilus", CommandType.commandTypeExplore)); break; - case desktopXfce: listDefault.add(getPresetData(listOS, "Xfce", CommandType.commandTypeOpen)); - listDefault.add(getPresetData(listOS, "Xfce", CommandType.commandTypeRun)); - listDefault.add(getPresetData(listOS, "Thunar", CommandType.commandTypeExplore)); + case desktopXfce: listDefault.add(getCommandData(listOS, "Xfce", CommandType.commandTypeOpen)); + listDefault.add(getCommandData(listOS, "Xfce", CommandType.commandTypeRun)); + listDefault.add(getCommandData(listOS, "Thunar", CommandType.commandTypeExplore)); break; default:; } @@ -165,17 +184,17 @@ public List getDefaultPresets() { } break; case osMacOSX: - listDefault.add(getPresetData(listOS, "Terminal", CommandType.commandTypeOpen)); - listDefault.add(getPresetData(listOS, "Terminal", CommandType.commandTypeRun)); - listDefault.add(getPresetData(listOS, "Finder", CommandType.commandTypeExplore)); + listDefault.add(getCommandData(listOS, "Terminal", CommandType.commandTypeOpen)); + listDefault.add(getCommandData(listOS, "Terminal", CommandType.commandTypeRun)); + listDefault.add(getCommandData(listOS, "Finder", CommandType.commandTypeExplore)); break; } // add clipboard - listDefault.add(getPresetData(listOS, ".*path", CommandType.commandTypeClipboard)); + listDefault.add(getCommandData(listOS, ".*path", CommandType.commandTypeClipboard)); return listDefault; } - private OS getOS() { + public static OS getOS() { OS os = OS.osUnknown; /* possible OS string: AIX @@ -221,19 +240,19 @@ private OS getOS() { return os; } - private static List getPresetData(List list, OS os) { + public static List getCommandData(List list, OS os) { List listOut = new ArrayList(); for (CommandData entry : list) { - if (entry.getOs() == os) { + if (entry.getOS() == os) { listOut.add(entry); } } return listOut; } - private static CommandData getPresetData(List list, String name, CommandType type) { + private static CommandData getCommandData(List list, String name, CommandType type) { for (CommandData entry : list) { - if (entry.getType() == type && entry.getName().matches(name)) { + if (entry.getCommandType() == type && entry.getName().matches(name)) { return entry; } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java similarity index 85% rename from plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDialog.java rename to plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java index 273a2f74..2575f898 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java @@ -21,7 +21,6 @@ import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; @@ -32,17 +31,16 @@ import de.anbos.eclipse.easyshell.plugin.Activator; -public class CommandDialog extends StatusDialog { +public class CommandDataDialog extends StatusDialog { private CommandData data; private boolean edit; - private Button enabledCheckBox; private Text nameText; private CCombo typeCombo; private Text valueText; - public CommandDialog(Shell parent, CommandData data, boolean edit) { + public CommandDataDialog(Shell parent, CommandData data, boolean edit) { super(parent); this.data = data; this.edit = edit; @@ -87,14 +85,12 @@ public Control createDialogArea(Composite parent) { GridData data1 = new GridData(GridData.FILL_HORIZONTAL); pageGroup1.setLayoutData(data1); pageGroup1.setFont(parent.getFont()); - // create activity checkbox - createEnabledCheckBox(pageGroup1); - // create rule type combo + // create type type combo createTypeCombo(pageGroup1); //create input nameText field nameText = createTextField(pageGroup1, Activator.getResourceString("easyshell.command.editor.dialog.name.label"), data.getName()); // create input valueText field - valueText = createTextField(pageGroup1, Activator.getResourceString("easyshell.command.editor.dialog.value.label"), data.getValue()); + valueText = createTextField(pageGroup1, Activator.getResourceString("easyshell.command.editor.dialog.value.label"), data.getCommand()); // ------------------------------------ Description ------------------------------------------ Label desc_label = new Label(pageComponent, 0); @@ -121,18 +117,16 @@ public Control createDialogArea(Composite parent) { } protected void okPressed() { - boolean rulesOK = validateRuleValues(); - if (!rulesOK) { + if (!validateValues()) { return; } - data.setEnabled(enabledCheckBox.getSelection()); - data.setType(CommandType.getFromName(typeCombo.getText())); + data.setCommandType(CommandType.getFromName(typeCombo.getText())); data.setName(nameText.getText()); - data.setValue(valueText.getText()); + data.setCommand(valueText.getText()); super.okPressed(); } - private boolean validateRuleValues() { + private boolean validateValues() { final String title = Activator.getResourceString("easyshell.command.editor.dialog.error.incompletedata.title"); @@ -165,21 +159,7 @@ private boolean validateRuleValues() { return valid; } - private void createEnabledCheckBox(Composite parent) { - // draw label - Label comboLabel = new Label(parent,SWT.LEFT); - comboLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END)); - comboLabel.setText(Activator.getResourceString("easyshell.command.editor.dialog.active.label")); //$NON-NLS-1$ - // draw checkbox - enabledCheckBox = new Button(parent,SWT.CHECK); - if(edit) { - enabledCheckBox.setSelection(this.data.isEnabled()); - } else { - enabledCheckBox.setSelection(true); - } - } - - private String[] getAllPresetTypesAsComboNames() { + private String[] getAllCommandTypesAsComboNames() { List list = CommandType.getNamesAsList(); String[] arr = new String[list.size()]; for (int i=0;i items; private DataObjectComparator comparator; - public CommandsStore(IPreferenceStore store) { + public CommandDataStore(IPreferenceStore store) { items = new ArrayList(); this.store = store; } @@ -46,32 +45,8 @@ public CommandData[] getAllCommandsArray() { return allArray; } - public List getAllEnabledCommands() { - List checkedItems = new ArrayList(); - Iterator dataIterator = items.iterator(); - while(dataIterator.hasNext()) { - CommandData data = (CommandData)dataIterator.next(); - if(data.isEnabled()) { - checkedItems.add(data); - } - } - return checkedItems; - } - - public CommandData[] getAllEnabledCommandsArray() { - List checkedItems = getAllEnabledCommands(); - if(checkedItems.size() <= 0) { - return new CommandData[0]; - } - CommandData[] checked = new CommandData[checkedItems.size()]; - for(int i = 0 ; i < checked.length ; i++) { - checked[i] = (CommandData)checkedItems.get(i); - } - return checked; - } - public CommandData getPreviousElement(CommandData data) { - sort(); + sort(); for(int i = 0 ; i < items.size() ; i++) { CommandData item = (CommandData)items.get(i); if(item.equals(data)) { @@ -86,7 +61,7 @@ public CommandData getPreviousElement(CommandData data) { } public CommandData getNextElement(CommandData data) { - sort(); + sort(); for(int i = 0 ; i < items.size() ; i++) { CommandData item = (CommandData)items.get(i); if(item.equals(data)) { @@ -101,7 +76,7 @@ public CommandData getNextElement(CommandData data) { } public CommandData getLastElement() { - sort(); + sort(); int index = items.size() - 1; if(index < 0) { return null; @@ -110,12 +85,12 @@ public CommandData getLastElement() { } public void add(CommandData data) { - int position = 0; - CommandData lastElement = getLastElement(); - if(lastElement != null) { - position = lastElement.getPosition() + 1; - } - data.setPosition(position); + int position = 0; + CommandData lastElement = getLastElement(); + if(lastElement != null) { + position = lastElement.getPosition() + 1; + } + data.setPosition(position); items.add(data); sort(); } @@ -126,16 +101,16 @@ public void delete(CommandData data) { } public void save() { - store.setValue(Constants.PREF_PRESETS,PreferenceValueConverter.asString(getAllCommands())); + store.setValue(Constants.PREF_COMMANDS,PreferenceValueConverter.asCommandDataString(getAllCommands())); } public void loadDefaults() { - store.setToDefault(Constants.PREF_PRESETS); + store.setToDefault(Constants.PREF_COMMANDS); load(); } public void load() { - CommandData[] items = PreferenceValueConverter.asPresetDataArray(store.getString(Constants.PREF_PRESETS)); + CommandData[] items = PreferenceValueConverter.asCommandDataArray(store.getString(Constants.PREF_COMMANDS)); this.items.clear(); for(int i = 0 ; i < items.length ; i++) { this.items.add(items[i]); @@ -147,39 +122,53 @@ public void removeAll() { items.clear(); } + public CommandData getCommandDataByName(String name) { + for (CommandData data : items) { + if (data.getName().equals(name)) { + return data; + } + } + return null; + } + + public CommandData getCommandDataByPosition(int position) { + return items.get(position); + } + private void sort() { - if(comparator == null) { - comparator = new DataObjectComparator(); - } - Collections.sort(items,comparator); - for (int i=0;i { - public int compare(Object object1, Object object2) { - CommandData data1 = null; - CommandData data2 = null; - if(object1 instanceof CommandData) { - data1 = (CommandData)object1; - } - if(object2 instanceof CommandData) { - data2 = (CommandData)object2; - } - if(data1 == null | data2 == null) { - return -1; - } - if(data1.getPosition() > data2.getPosition()) { - return 1; - } - if(data1.getPosition() == data2.getPosition()) { - return 0; - } - if(data1.getPosition() < data2.getPosition()) { - return -1; - } - return -1; - } + public int compare(Object object1, Object object2) { + CommandData data1 = null; + CommandData data2 = null; + if(object1 instanceof CommandData) { + data1 = (CommandData)object1; + } + if(object2 instanceof CommandData) { + data2 = (CommandData)object2; + } + if(data1 == null || data2 == null) { + return -1; + } + if(data1.getPosition() > data2.getPosition()) { + return 1; + } + if(data1.getPosition() == data2.getPosition()) { + return 0; + } + if(data1.getPosition() < data2.getPosition()) { + return -1; + } + return -1; + } } + } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuData.java new file mode 100644 index 00000000..3ac76dd9 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuData.java @@ -0,0 +1,119 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +import java.util.StringTokenizer; +import java.util.UUID; + +public class CommandMenuData { + + // status + private int position = 0; + private boolean enabled = true; + + // menu + private String id = UUID.randomUUID().toString(); + private String name = null; + + // command data + private CommandData commandData; + + public CommandMenuData(CommandData commandData) { + this.commandData = commandData; + setDefaultName(); + } + + public CommandMenuData() { + } + + public int getPosition() { + return position; + } + + public boolean isEnabled() { + return enabled; + } + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public CommandData getCommandData() { + return commandData; + } + + public boolean equals(Object object) { + if(!(object instanceof CommandMenuData)) { + return false; + } + CommandMenuData data = (CommandMenuData)object; + if( data.getPosition() == this.getPosition() && + data.getName().equals(this.getName()) && + data.getCommandData().equals(this.getCommandData()) + ) + { + return true; + } + return false; + } + + public boolean deserialize(String value, StringTokenizer tokenizer, String delimiter) { + if((value == null || value.length() <= 0) && tokenizer == null) { + return false; + } + if (tokenizer == null) { + tokenizer = new StringTokenizer(value,delimiter); + } + // set members + setPosition(Integer.parseInt(tokenizer.nextToken())); + setEnabled(Boolean.valueOf(tokenizer.nextToken()).booleanValue()); + setId(tokenizer.nextToken()); + setName(tokenizer.nextToken()); + // + setCommandData(new CommandData()); + getCommandData().deserialize(null, tokenizer, delimiter); + return true; + } + + public String serialize(String delimiter) { + return Integer.toString(getPosition()) + delimiter + Boolean.toString(isEnabled())+ delimiter + getId() + delimiter + getName() + delimiter + commandData.serialize(delimiter); + } + + public void setPosition(int position) { + this.position = position; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public void setId(String id) { + this.id = id; + } + + public void setName(String name) { + this.name = name; + } + + public void setDefaultName() { + this.name = getCommandData().getCommandType().getName() + ": " + getCommandData().getName(); + } + + public void setCommandData(CommandData commandData) { + this.commandData = commandData; + } + +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandContentProvider.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuDataContentProvider.java similarity index 77% rename from plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandContentProvider.java rename to plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuDataContentProvider.java index e6006320..a105f1de 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandContentProvider.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuDataContentProvider.java @@ -14,12 +14,12 @@ import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.Viewer; -public class CommandContentProvider implements IStructuredContentProvider { +public class CommandMenuDataContentProvider implements IStructuredContentProvider { - private CommandsStore store; + private CommandMenuDataStore store; public Object[] getElements(Object inputElement) { - return store.getAllCommandsArray(); + return store.getCommandMenuDataArray(); } public void dispose() { @@ -27,8 +27,8 @@ public void dispose() { } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - if(newInput instanceof CommandsStore) { - store = (CommandsStore)newInput; + if(newInput instanceof CommandMenuDataStore) { + store = (CommandMenuDataStore)newInput; } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuDataDialog.java new file mode 100644 index 00000000..8e7c086d --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuDataDialog.java @@ -0,0 +1,224 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +import java.util.List; + +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.dialogs.StatusDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CCombo; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +import de.anbos.eclipse.easyshell.plugin.Activator; + +public class CommandMenuDataDialog extends StatusDialog { + + private CommandMenuData data; + private CommandDataStore cmdStore; + private List cmdList; + private boolean edit; + + private Button enabledCheckBox; + private Text nameText; + private Text commandText; + private CCombo commandCombo; + + public CommandMenuDataDialog(Shell parent, CommandMenuData data, CommandDataStore cmdStore, List cmdList, boolean edit) { + super(parent); + this.data = data; + this.cmdStore = cmdStore; + this.cmdList = cmdList; + this.edit = edit; + // do layout and title + setShellStyle(getShellStyle() | SWT.MAX); + // set title + String title = null; + if(edit) { + title = Activator.getResourceString("easyshell.menu.editor.dialog.edit.title"); //$NON-NLS-1$ + } else { + title = Activator.getResourceString("easyshell.menu.editor.dialog.new.title"); //$NON-NLS-1$ + } + setTitle(title); + } + + @Override + protected boolean isResizable() { + return true; + } + + public Control createDialogArea(Composite parent) { + Composite pageComponent = new Composite(parent,SWT.NULL); + GridLayout layout0 = new GridLayout(); + layout0.numColumns = 1; + layout0.makeColumnsEqualWidth = false; + layout0.marginWidth = 5; + layout0.marginHeight = 4; + pageComponent.setLayout(layout0); + GridData data0 = new GridData(GridData.FILL_HORIZONTAL); + data0.widthHint = 640; + pageComponent.setLayoutData(data0); + pageComponent.setFont(parent.getFont()); + // define group1 + Group pageGroup1 = new Group(pageComponent, SWT.SHADOW_ETCHED_IN); + pageGroup1.setText(Activator.getResourceString("easyshell.menu.editor.dialog.title")); + GridLayout layout1 = new GridLayout(); + layout1.numColumns = 2; + layout1.makeColumnsEqualWidth = false; + layout1.marginWidth = 5; + layout1.marginHeight = 4; + pageGroup1.setLayout(layout1); + GridData data1 = new GridData(GridData.FILL_HORIZONTAL); + pageGroup1.setLayoutData(data1); + pageGroup1.setFont(parent.getFont()); + // create activity checkbox + createEnabledCheckBox(pageGroup1); + // create selected command combo + createCommandCombo(pageGroup1); + //create input nameText field + commandText = createTextField(pageGroup1, Activator.getResourceString("easyshell.menu.editor.dialog.command.label"), data.getCommandData().getCommand(), false); + //create input nameText field + nameText = createTextField(pageGroup1, Activator.getResourceString("easyshell.menu.editor.dialog.name.label"), data.getName(), true); + + //if (edit) { + // send event to refresh + Event event = new Event(); + event.item = null; + commandCombo.notifyListeners(SWT.Selection, event); + //} + + return pageComponent; + } + + protected void okPressed() { + if (!validateValues()) { + return; + } + data.setEnabled(enabledCheckBox.getSelection()); + data.setCommandData(cmdList.get(commandCombo.getSelectionIndex())); + data.setName(nameText.getText()); + super.okPressed(); + } + + private boolean validateValues() { + + final String title = Activator.getResourceString("easyshell.menu.editor.dialog.error.incompletedata.title"); + + // check type + if ( (commandCombo.getText() == null) || (commandCombo.getText().length() <= 0)) { + MessageDialog.openError(getShell(), title, Activator.getResourceString("easyshell.menu.editor.dialog.error.type.text")); + return false; + } + + boolean valid = true; + + // check name + String text = Activator.getResourceString("easyshell.menu.editor.dialog.error.name.text"); + if ( (nameText.getText() == null) || (nameText.getText().length() <= 0)) { + valid = false; + } + + // show error message + if (!valid) { + MessageDialog.openError(getShell(), title, text); + } + return valid; + } + + private void createEnabledCheckBox(Composite parent) { + // draw label + Label comboLabel = new Label(parent,SWT.LEFT); + comboLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END)); + comboLabel.setText(Activator.getResourceString("easyshell.menu.editor.dialog.active.label")); //$NON-NLS-1$ + // draw checkbox + enabledCheckBox = new Button(parent,SWT.CHECK); + if(edit) { + enabledCheckBox.setSelection(this.data.isEnabled()); + } else { + enabledCheckBox.setSelection(true); + } + } + + private String[] getAllCommandsAsComboNames(List list) { + String[] arr = new String[list.size()]; + for (int i=0;i items; + private DataObjectComparator comparator; + + public CommandMenuDataStore(IPreferenceStore store) { + items = new ArrayList(); + this.store = store; + } + + public List getCommandMenuDataList() { + return items; + } + + public CommandMenuData[] getCommandMenuDataArray() { + List allItems = getCommandMenuDataList(); + if(allItems.size() <= 0) { + return new CommandMenuData[0]; + } + CommandMenuData[] allArray = new CommandMenuData[allItems.size()]; + for(int i = 0 ; i < allArray.length ; i++) { + allArray[i] = (CommandMenuData)allItems.get(i); + } + return allArray; + } + + public List getEnabledCommandMenuDataList() { + List checkedItems = new ArrayList(); + Iterator dataIterator = items.iterator(); + while(dataIterator.hasNext()) { + CommandMenuData data = (CommandMenuData)dataIterator.next(); + if(data.isEnabled()) { + checkedItems.add(data); + } + } + return checkedItems; + } + + public CommandMenuData[] getEnabledCommandMenuDataArray() { + List checkedItems = getEnabledCommandMenuDataList(); + if(checkedItems.size() <= 0) { + return new CommandMenuData[0]; + } + CommandMenuData[] checked = new CommandMenuData[checkedItems.size()]; + for(int i = 0 ; i < checked.length ; i++) { + checked[i] = (CommandMenuData)checkedItems.get(i); + } + return checked; + } + + public CommandMenuData getPreviousElement(CommandMenuData data) { + sort(); + for(int i = 0 ; i < items.size() ; i++) { + CommandMenuData item = (CommandMenuData)items.get(i); + if(item.equals(data)) { + try { + return (CommandMenuData)items.get(i - 1); + } catch(Throwable t) { + return null; + } + } + } + return null; + } + + public CommandMenuData getNextElement(CommandMenuData data) { + sort(); + for(int i = 0 ; i < items.size() ; i++) { + CommandMenuData item = (CommandMenuData)items.get(i); + if(item.equals(data)) { + try { + return (CommandMenuData)items.get(i + 1); + } catch(Throwable t) { + return null; + } + } + } + return null; + } + + public CommandMenuData getLastElement() { + sort(); + int index = items.size() - 1; + if(index < 0) { + return null; + } + return (CommandMenuData)items.get(index); + } + + public void add(CommandMenuData data) { + int position = 0; + CommandMenuData lastElement = getLastElement(); + if(lastElement != null) { + position = lastElement.getPosition() + 1; + } + data.setPosition(position); + items.add(data); + sort(); + } + + public void delete(CommandMenuData data) { + items.remove(data); + sort(); + } + + public void save() { + store.setValue(Constants.PREF_MENU,PreferenceValueConverter.asCommandMenuDataString(getCommandMenuDataList())); + } + + public void loadDefaults() { + store.setToDefault(Constants.PREF_MENU); + load(); + } + + public void load() { + CommandMenuData[] items = PreferenceValueConverter.asCommandMenuDataArray(store.getString(Constants.PREF_MENU)); + this.items.clear(); + for(int i = 0 ; i < items.length ; i++) { + this.items.add(items[i]); + } + sort(); + } + + public void removeAll() { + items.clear(); + } + + private void sort() { + if(comparator == null) { + comparator = new DataObjectComparator(); + } + Collections.sort(items,comparator); + for (int i=0;i { + public int compare(Object object1, Object object2) { + CommandMenuData data1 = null; + CommandMenuData data2 = null; + if(object1 instanceof CommandMenuData) { + data1 = (CommandMenuData)object1; + } + if(object2 instanceof CommandMenuData) { + data2 = (CommandMenuData)object2; + } + if(data1 == null || data2 == null) { + return -1; + } + if(data1.getPosition() > data2.getPosition()) { + return 1; + } + if(data1.getPosition() == data2.getPosition()) { + return 0; + } + if(data1.getPosition() < data2.getPosition()) { + return -1; + } + return -1; + } + } +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandType.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandType.java index 37978a65..371f6453 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandType.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandType.java @@ -65,6 +65,16 @@ public static CommandType getFromName(String name) { } return ret; } + public static CommandType getFromEnum(String name) { + CommandType ret = commandTypeUnknown; + for(int i = 0; i < CommandType.values().length; i++) { + if (CommandType.values()[i].toString().equals(name)) { + ret = CommandType.values()[i]; + break; + } + } + return ret; + } public static CommandType getFromAction(String action) { CommandType ret = commandTypeUnknown; for(int i = 0; i < CommandType.values().length; i++) { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsPage.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsPage.java index 4d5e153d..be11ac1d 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsPage.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsPage.java @@ -12,6 +12,7 @@ package de.anbos.eclipse.easyshell.plugin.preferences; import java.util.Iterator; +import java.util.List; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.viewers.CheckStateChangedEvent; @@ -51,8 +52,10 @@ public class CommandsPage extends org.eclipse.jface.preference.PreferencePage private static final int TABLE_WIDTH = 400; private Table table; - private ItemMover itemMover; - private CommandsStore store; + private CommandMenuDataMover itemMover; + private CommandDataStore cmdStore; + List cmdList; + private CommandMenuDataStore menuStore; private CheckboxTableViewer tableViewer; private Button addButton; private Button editButton; @@ -66,14 +69,14 @@ public void init(IWorkbench workbench) { @Override public boolean performOk() { - store.save(); + menuStore.save(); return true; } @Override protected void performDefaults() { - store.loadDefaults(); - for (CommandData item : store.getAllEnabledCommands()) { + menuStore.loadDefaults(); + for (CommandMenuData item : menuStore.getCommandMenuDataList()) { tableViewer.setChecked(item, true); } //tableViewer.refresh(); @@ -117,13 +120,22 @@ protected Control createContents(Composite parent) { table.setLayoutData(data); tableViewer = new CheckboxTableViewer(table); - tableViewer.setLabelProvider(new CommandLabelProvider()); - tableViewer.setContentProvider(new CommandContentProvider()); - store = new CommandsStore(Activator.getDefault().getPreferenceStore()); - store.load(); - tableViewer.setInput(store); + tableViewer.setLabelProvider(new CommandMenuDataLabelProvider()); + tableViewer.setContentProvider(new CommandMenuDataContentProvider()); + + // command store + cmdStore = new CommandDataStore(Activator.getDefault().getPreferenceStore()); + cmdStore.load(); + + // get the native commands list + cmdList = CommandDataDefaultCollection.getCommandsNative(cmdStore.getAllCommands()); + + // menu store + menuStore = new CommandMenuDataStore(Activator.getDefault().getPreferenceStore()); + menuStore.load(); + tableViewer.setInput(menuStore); tableViewer.setAllChecked(false); - tableViewer.setCheckedElements(store.getAllEnabledCommandsArray()); + tableViewer.setCheckedElements(menuStore.getEnabledCommandMenuDataArray()); tableViewer.addDoubleClickListener(new IDoubleClickListener() { @Override @@ -135,7 +147,7 @@ public void doubleClick(DoubleClickEvent event) { tableViewer.addCheckStateListener(new ICheckStateListener() { @Override public void checkStateChanged(CheckStateChangedEvent event) { - CommandData data = (CommandData) event.getElement(); + CommandMenuData data = (CommandMenuData) event.getElement(); data.setEnabled(event.getChecked()); } }); @@ -154,11 +166,11 @@ public void selectionChanged(SelectionChangedEvent event) { tableViewer.setSorter(new ViewerSorter() { public int compare(Viewer viewer, Object object1, Object object2) { - if (!(object1 instanceof CommandData) || !(object2 instanceof CommandData)) { + if (!(object1 instanceof CommandMenuData) || !(object2 instanceof CommandMenuData)) { return super.compare(viewer, object1, object2); } - CommandData data1 = (CommandData) object1; - CommandData data2 = (CommandData) object2; + CommandMenuData data1 = (CommandMenuData) object1; + CommandMenuData data2 = (CommandMenuData) object2; if (data1.getPosition() > data2.getPosition()) { return 1; } @@ -176,7 +188,7 @@ public boolean isSorterProperty(Object element, String property) { } }); - itemMover = new ItemMover(table, store); + itemMover = new CommandMenuDataMover(table, menuStore); // button pageComponent Composite groupComponent = new Composite(pageComponent, SWT.NULL); @@ -356,10 +368,11 @@ public void controlResized(ControlEvent e) { } private void add() { - CommandData data = new CommandData(); - CommandDialog dialog = new CommandDialog(getShell(), data, false); + CommandMenuData data = new CommandMenuData(); + data.setCommandData(cmdList.get(0)); + CommandMenuDataDialog dialog = new CommandMenuDataDialog(getShell(), data, cmdStore, cmdList, false); if (dialog.open() == Window.OK) { - store.add(data); + menuStore.add(data); tableViewer.refresh(); tableViewer.setChecked(data, data.isEnabled()); tableViewer.setSelection(new StructuredSelection(data)); @@ -371,16 +384,16 @@ private void remove() { IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection(); Iterator elements = selection.iterator(); while (elements.hasNext()) { - CommandData data = (CommandData) elements.next(); - store.delete(data); + CommandMenuData data = (CommandMenuData) elements.next(); + menuStore.delete(data); } tableViewer.refresh(); } private void edit() { IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection(); - CommandData data = (CommandData) selection.getFirstElement(); - CommandDialog dialog = new CommandDialog(getShell(), data, true); + CommandMenuData data = (CommandMenuData) selection.getFirstElement(); + CommandMenuDataDialog dialog = new CommandMenuDataDialog(getShell(), data, cmdStore, cmdList, true); if (dialog.open() == Window.OK) { tableViewer.refresh(); tableViewer.setChecked(data, data.isEnabled()); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Constants.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Constants.java index e5c771cf..aff1e5c0 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Constants.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Constants.java @@ -14,7 +14,7 @@ public interface Constants { // Plugin - public static final String PLUGIN_ID = "de.anbos.eclipse.easyshell.plugin"; //$NON-NLS-1$ + public static final String PLUGIN_ID = "de.anbos.eclipse.easyshell.plugin"; // Images public static final String IMAGE_PATH = "icons/"; @@ -26,7 +26,8 @@ public interface Constants { public static final String IMAGE_OTHER = "editor.gif"; // Preferences - public static final String PREF_PRESETS = "PRESETS"; //$NON-NLS-1$ + public static final String PREF_COMMANDS = "COMMANDS"; + public static final String PREF_MENU = "MENU"; // Actions public static final String ACTION_UNKNOWN = "de.anbos.eclipse.easyshell.plugin.commands.Unknown"; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Debug.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Debug.java index da7c53c9..ed88266d 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Debug.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Debug.java @@ -15,24 +15,25 @@ * Debug. */ public enum Debug { + debugUnknown(-1, "Unknown"), debugNo(0, "No"), debugYes(1, "Yes"); // attributes private final int id; - private final String mode; + private final String name; // construct - Debug(int id, String mode) { + Debug(int id, String name) { this.id = id; - this.mode = mode; + this.name = name; } public int getId() { return id; } - public String getMode() { - return mode; + public String getName() { + return name; } public static Debug getFromId(int id) { - Debug ret = debugNo; + Debug ret = debugUnknown; for(int i = 0; i < Debug.values().length; i++) { if (Debug.values()[i].getId() == id) { ret = Debug.values()[i]; @@ -41,4 +42,24 @@ public static Debug getFromId(int id) { } return ret; } + public static Debug getFromName(String name) { + Debug ret = debugUnknown; + for(int i = 0; i < Debug.values().length; i++) { + if (Debug.values()[i].getName().equals(name)) { + ret = Debug.values()[i]; + break; + } + } + return ret; + } + public static Debug getFromEnum(String name) { + Debug ret = debugUnknown; + for(int i = 0; i < Debug.values().length; i++) { + if (Debug.values()[i].toString().equals(name)) { + ret = Debug.values()[i]; + break; + } + } + return ret; + } } \ No newline at end of file diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java index be9ac540..e42c9218 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java @@ -20,8 +20,10 @@ public class Initializer extends AbstractPreferenceInitializer { public void initializeDefaultPreferences() { IPreferenceStore store = Activator.getDefault().getPreferenceStore(); - String defaultPresets = PreferenceValueConverter.asString(CommandDataDefaultCollection.getDefaultPresetsStatic()); - store.setDefault(Constants.PREF_PRESETS,defaultPresets); + String defaultCommand = PreferenceValueConverter.asCommandDataString(CommandDataDefaultCollection.getAllCommandsStatic()); + String defaultMenu = PreferenceValueConverter.asCommandMenuDataString(CommandDataDefaultCollection.getDefaultCommandsMenuStatic()); + store.setDefault(Constants.PREF_COMMANDS, defaultCommand); + store.setDefault(Constants.PREF_MENU, defaultMenu); //getDefaultPresets(); /* store.setDefault(PreferenceConstants.P_BOOLEAN, true); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/LinuxDesktop.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/LinuxDesktop.java index 4ee1069c..26980d64 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/LinuxDesktop.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/LinuxDesktop.java @@ -15,12 +15,11 @@ * Linux desktops. */ public enum LinuxDesktop { - desktopUnknown(0, "Unknown"), + desktopUnknown(-1, "Unknown"), + desktopXfce(0, "Xfce"), desktopKde(1, "KDE"), desktopGnome(2, "Gnome"), - desktopCinnamon(3, "Cinnamon"), - desktopCde(4, "CDE"), - desktopXfce(5, "Xfce"); + desktopCinnamon(3, "Cinnamon"); // attributes private final int id; private final String name; @@ -45,4 +44,24 @@ public static LinuxDesktop getFromId(int id) { } return ret; } + public static LinuxDesktop getFromName(String name) { + LinuxDesktop ret = desktopUnknown; + for(int i = 0; i < LinuxDesktop.values().length; i++) { + if (LinuxDesktop.values()[i].getName().equals(name)) { + ret = LinuxDesktop.values()[i]; + break; + } + } + return ret; + } + public static LinuxDesktop getFromEnum(String name) { + LinuxDesktop ret = desktopUnknown; + for(int i = 0; i < LinuxDesktop.values().length; i++) { + if (LinuxDesktop.values()[i].toString().equals(name)) { + ret = LinuxDesktop.values()[i]; + break; + } + } + return ret; + } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/OS.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/OS.java index ff9b76cb..dac1c722 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/OS.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/OS.java @@ -15,10 +15,10 @@ import java.util.List; public enum OS { - osUnknown(0, "Unknown"), - osWindows(1, "Windows"), - osLinux(2, "Linux"), - osMacOSX(3, "MAC OS X"); + osUnknown(-1, "Unknown"), + osWindows(0, "Windows"), + osLinux(1, "Linux"), + osMacOSX(2, "MAC OS X"); // attributes private final int id; private final String name; @@ -53,6 +53,16 @@ public static OS getFromName(String name) { } return ret; } + public static OS getFromEnum(String name) { + OS ret = osUnknown; + for(int i = 0; i < OS.values().length; i++) { + if (OS.values()[i].toString().equals(name)) { + ret = OS.values()[i]; + break; + } + } + return ret; + } public static List getNamesAsList() { List list = new ArrayList(); for(int i = 0; i < OS.values().length; i++) { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceValueConverter.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceValueConverter.java index f5eec585..8bb445be 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceValueConverter.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceValueConverter.java @@ -11,12 +11,9 @@ package de.anbos.eclipse.easyshell.plugin.preferences; -import java.nio.charset.StandardCharsets; import java.util.List; import java.util.StringTokenizer; -import org.eclipse.core.internal.preferences.Base64; - public class PreferenceValueConverter { // Constant ---------------------------------------------------------------- @@ -26,49 +23,59 @@ public class PreferenceValueConverter { // Static ------------------------------------------------------------------ - public static String asString(List items) { + public static String asCommandDataString(List items) { StringBuffer buffer = new StringBuffer(); for(CommandData item : items) { - buffer.append(asString(item)); + buffer.append(asCommandDataString(item)); + buffer.append(ITEM_DELIMITER); + } + return buffer.toString(); + } + + public static String asCommandMenuDataString(List items) { + StringBuffer buffer = new StringBuffer(); + for(CommandMenuData item : items) { + buffer.append(asCommandMenuDataString(item)); buffer.append(ITEM_DELIMITER); } return buffer.toString(); } - public static final String asString(CommandData data) { - String position = Integer.toString(data.getPosition()); - String enabled = Boolean.toString(data.isEnabled()); - String id = data.getId(); - String name = data.getName(); - String type = data.getType().getName(); - String value = data.getValue(); - String os = data.getOs().getName(); - return position + VALUE_DELIMITER + enabled + VALUE_DELIMITER + id + VALUE_DELIMITER + name + VALUE_DELIMITER + type + VALUE_DELIMITER + value + VALUE_DELIMITER + os + VALUE_DELIMITER; + public static final String asCommandDataString(CommandData data) { + return data.serialize(VALUE_DELIMITER); } - /* - public static final String asStringBase64(PresetData data) { - String position = Base64.encode(Integer.toString(data.getPosition()).getBytes(StandardCharsets.UTF_8)).toString(); - String checked = Base64.encode(Boolean.toString(data.isEnabled()).getBytes(StandardCharsets.UTF_8)).toString(); - String name = Base64.encode(data.getName().getBytes(StandardCharsets.UTF_8)).toString(); - String type = Base64.encode(data.getType().getBytes(StandardCharsets.UTF_8)).toString(); - String value = Base64.encode(data.getValue().getBytes(StandardCharsets.UTF_8)).toString(); - return position + VALUE_DELIMITER + checked + VALUE_DELIMITER + name + VALUE_DELIMITER + type + VALUE_DELIMITER + value + VALUE_DELIMITER; + public static final String asCommandMenuDataString(CommandMenuData data) { + return data.serialize(VALUE_DELIMITER); } - */ - public static CommandData[] asPresetDataArray(String value) { + public static CommandData[] asCommandDataArray(String value) { StringTokenizer tokenizer = new StringTokenizer(value,ITEM_DELIMITER); CommandData[] items = new CommandData[tokenizer.countTokens()]; for(int i = 0 ; i < items.length ; i++) { - items[i] = asPresetData(tokenizer.nextToken()); + items[i] = asCommandData(tokenizer.nextToken()); + } + return items; + } + + public static CommandMenuData[] asCommandMenuDataArray(String value) { + StringTokenizer tokenizer = new StringTokenizer(value,ITEM_DELIMITER); + CommandMenuData[] items = new CommandMenuData[tokenizer.countTokens()]; + for(int i = 0 ; i < items.length ; i++) { + items[i] = asCommandMenuData(tokenizer.nextToken()); } return items; } - public static CommandData asPresetData(String value) { + public static CommandData asCommandData(String value) { CommandData data = new CommandData(); - data.fillTokens(value, VALUE_DELIMITER); + data.deserialize(value, null, VALUE_DELIMITER); + return data; + } + + public static CommandMenuData asCommandMenuData(String value) { + CommandMenuData data = new CommandMenuData(); + data.deserialize(value, null, VALUE_DELIMITER); return data; } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Quotes.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Quotes.java index e7cb65ff..44d501f8 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Quotes.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Quotes.java @@ -22,6 +22,7 @@ * Quotes. */ public enum Quotes { + quotesUnknown(-1, "Unknown"), quotesNo(0, "No"), quotesSingle(1, "Single"), quotesDouble(2, "Double"), @@ -30,20 +31,20 @@ public enum Quotes { quotesEscape(5, "Escape"); // check if no quotes and space in string, then escape // attributes private final int id; - private final String mode; + private final String name; // construct - Quotes(int id, String mode) { + Quotes(int id, String name) { this.id = id; - this.mode = mode; + this.name = name; } public int getId() { return id; } - public String getMode() { - return mode; + public String getName() { + return name; } public static Quotes getFromId(int id) { - Quotes ret = quotesNo; + Quotes ret = quotesUnknown; for(int i = 0; i < Quotes.values().length; i++) { if (Quotes.values()[i].getId() == id) { ret = Quotes.values()[i]; @@ -52,4 +53,24 @@ public static Quotes getFromId(int id) { } return ret; } + public static Quotes getFromName(String name) { + Quotes ret = quotesUnknown; + for(int i = 0; i < Quotes.values().length; i++) { + if (Quotes.values()[i].getName().equals(name)) { + ret = Quotes.values()[i]; + break; + } + } + return ret; + } + public static Quotes getFromEnum(String name) { + Quotes ret = quotesUnknown; + for(int i = 0; i < Quotes.values().length; i++) { + if (Quotes.values()[i].toString().equals(name)) { + ret = Quotes.values()[i]; + break; + } + } + return ret; + } } \ No newline at end of file diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/RessourceType.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/RessourceType.java new file mode 100644 index 00000000..309890a1 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/RessourceType.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +import java.util.ArrayList; +import java.util.List; + +public enum RessourceType { + ressourceTypeUnknown(-1, "Unknown"), + ressourceTypeFile(0, "File"), + ressourceTypeFolder(1, "Folder"), + ressourceFileOrFolder(2, "File or Folder"); + // attributes + private final int id; + private final String name; + // construct + RessourceType(int id, String name) { + this.id = id; + this.name = name; + } + public int getId() { + return id; + } + public String getName() { + return name; + } + public static RessourceType getFromId(int id) { + RessourceType ret = ressourceTypeUnknown; + for(int i = 0; i < RessourceType.values().length; i++) { + if (RessourceType.values()[i].getId() == id) { + ret = RessourceType.values()[i]; + break; + } + } + return ret; + } + public static RessourceType getFromName(String name) { + RessourceType ret = ressourceTypeUnknown; + for(int i = 0; i < RessourceType.values().length; i++) { + if (RessourceType.values()[i].getName().equals(name)) { + ret = RessourceType.values()[i]; + break; + } + } + return ret; + } + public static RessourceType getFromEnum(String name) { + RessourceType ret = ressourceTypeUnknown; + for(int i = 0; i < RessourceType.values().length; i++) { + if (RessourceType.values()[i].toString().equals(name)) { + ret = RessourceType.values()[i]; + break; + } + } + return ret; + } + public static List getNamesAsList() { + List list = new ArrayList(); + for(int i = 0; i < RessourceType.values().length; i++) { + if (RessourceType.values()[i] != ressourceTypeUnknown) { + list.add(RessourceType.values()[i].getName()); + } + } + return list; + } +} \ No newline at end of file diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Tokenizer.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Tokenizer.java index 7f077a10..475165b1 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Tokenizer.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Tokenizer.java @@ -11,28 +11,26 @@ package de.anbos.eclipse.easyshell.plugin.preferences; -/** - * Tokenizer. - */ public enum Tokenizer { - EasyShellTokenizerNo(0, "No"), - EasyShellTokenizerYes(1, "Yes"); + tokenizerUnknown(-1, "Unknown"), + tokenizerNo(0, "No"), + tokenizerYes(1, "Yes"); // attributes private final int id; - private final String mode; + private final String name; // construct Tokenizer(int id, String mode) { this.id = id; - this.mode = mode; + this.name = mode; } public int getId() { return id; } - public String getMode() { - return mode; + public String getName() { + return name; } public static Tokenizer getFromId(int id) { - Tokenizer ret = EasyShellTokenizerYes; + Tokenizer ret = tokenizerUnknown; for(int i = 0; i < Tokenizer.values().length; i++) { if (Tokenizer.values()[i].getId() == id) { ret = Tokenizer.values()[i]; @@ -41,4 +39,24 @@ public static Tokenizer getFromId(int id) { } return ret; } + public static Tokenizer getFromName(String name) { + Tokenizer ret = tokenizerUnknown; + for(int i = 0; i < Tokenizer.values().length; i++) { + if (Tokenizer.values()[i].getName().equals(name)) { + ret = Tokenizer.values()[i]; + break; + } + } + return ret; + } + public static Tokenizer getFromEnum(String name) { + Tokenizer ret = tokenizerUnknown; + for(int i = 0; i < Tokenizer.values().length; i++) { + if (Tokenizer.values()[i].toString().equals(name)) { + ret = Tokenizer.values()[i]; + break; + } + } + return ret; + } }; From ec2b937648aa11458d1338e98987e7df86191f3d Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Tue, 12 Jul 2016 11:10:36 +0200 Subject: [PATCH 04/73] enabled command dialog - enabled Add and Edit buttons for commands - fixed table refresh Signed-off-by: Andre Bossert --- .../eclipse/easyshell/plugin/Activator.java | 1 - .../easyshell/plugin/UIMessages.properties | 19 ++-- .../plugin/actions/ActionDelegate.java | 2 +- .../plugin/preferences/CommandDataDialog.java | 2 +- .../plugin/preferences/CommandMenuData.java | 7 +- .../preferences/CommandMenuDataDialog.java | 99 ++++++++++++++++--- .../plugin/preferences/CommandsPage.java | 38 +++---- 7 files changed, 122 insertions(+), 46 deletions(-) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java index 4c06e2ba..ac2e4bef 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java @@ -13,7 +13,6 @@ import java.net.URL; import java.text.MessageFormat; -import java.util.List; import java.util.MissingResourceException; import java.util.ResourceBundle; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties index 436fe72c..b548cfb5 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties @@ -3,31 +3,30 @@ easyshell.properties.main.page.title=EasyShell easyshell.properties.commands.page.title=Presets easyshell.actionset.name=EasyShell -easyshell.command.editor.table.header.column0.title=Name -easyshell.command.editor.table.header.column1.title=Command -easyshell.command.editor.button.add=Add... -easyshell.command.editor.button.edit=Edit... -easyshell.command.editor.button.remove=Remove -easyshell.command.editor.button.up=Up -easyshell.command.editor.button.down=Down +easyshell.page.table.header.column0.title=Name +easyshell.page.table.header.column1.title=Command +easyshell.page.table.button.add=Add... +easyshell.page.table.button.edit=Edit... +easyshell.page.table.button.remove=Remove +easyshell.page.table.button.up=Up +easyshell.page.table.button.down=Down easyshell.command.editor.dialog.new.title=Create new command easyshell.command.editor.dialog.edit.title=Edit existing command easyshell.command.editor.dialog.title=Command definition - easyshell.command.editor.dialog.error.incompletedata.title=Missing or wrong command detected easyshell.command.editor.dialog.error.type.text=Please choose a type easyshell.command.editor.dialog.error.name.text=Please enter a valid name easyshell.command.editor.dialog.error.value.text=Please enter a valid command +easyshell.command.editor.dialog.combo.label=type: easyshell.command.editor.dialog.name.label=name: easyshell.command.editor.dialog.value.label=command: easyshell.menu.editor.dialog.new.title=Create new menu easyshell.menu.editor.dialog.edit.title=Edit existing menu easyshell.menu.editor.dialog.title=Menu definition +easyshell.menu.editor.dialog.error.name.text=Please enter a valid name easyshell.menu.editor.dialog.active.label=enabled: easyshell.menu.editor.dialog.name.label=menu name: easyshell.menu.editor.dialog.combo.label=preset: easyshell.menu.editor.dialog.command.label=command: - -easyshell.menu.editor.dialog.error.name.text=Please enter a valid name diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java index fd03b375..d5d560a3 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java @@ -74,7 +74,7 @@ public void run(IAction action) { } // get the ID - String ActionIDStr = action.getId(); + //String ActionIDStr = action.getId(); //Activator.getDefault().sysout(true, "Action ID: >" + ActionIDStr + "<"); // String for all commands in case of clipboard diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java index 2575f898..9741519b 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java @@ -182,7 +182,7 @@ private void createTypeCombo(Composite parent) { typeCombo.addSelectionListener(new SelectionListener() { @Override public void widgetSelected(SelectionEvent e) { - String text = typeCombo.getItem(typeCombo.getSelectionIndex()); + //String text = typeCombo.getItem(typeCombo.getSelectionIndex()); } @Override public void widgetDefaultSelected(SelectionEvent e) { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuData.java index 3ac76dd9..dbf8fca4 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuData.java @@ -83,7 +83,7 @@ public boolean deserialize(String value, StringTokenizer tokenizer, String delim setId(tokenizer.nextToken()); setName(tokenizer.nextToken()); // - setCommandData(new CommandData()); + setCommandData(new CommandData(), false); getCommandData().deserialize(null, tokenizer, delimiter); return true; } @@ -112,8 +112,11 @@ public void setDefaultName() { this.name = getCommandData().getCommandType().getName() + ": " + getCommandData().getName(); } - public void setCommandData(CommandData commandData) { + public void setCommandData(CommandData commandData, boolean setDefaultName) { this.commandData = commandData; + if (setDefaultName) { + setDefaultName(); + } } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuDataDialog.java index 8e7c086d..2c70a11b 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuDataDialog.java @@ -15,10 +15,13 @@ import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.StatusDialog; +import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CCombo; +import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Font; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; @@ -44,6 +47,9 @@ public class CommandMenuDataDialog extends StatusDialog { private Text commandText; private CCombo commandCombo; + private Button addButton; + private Button editButton; + public CommandMenuDataDialog(Shell parent, CommandMenuData data, CommandDataStore cmdStore, List cmdList, boolean edit) { super(parent); this.data = data; @@ -68,6 +74,7 @@ protected boolean isResizable() { } public Control createDialogArea(Composite parent) { + Font font = parent.getFont(); Composite pageComponent = new Composite(parent,SWT.NULL); GridLayout layout0 = new GridLayout(); layout0.numColumns = 1; @@ -75,10 +82,10 @@ public Control createDialogArea(Composite parent) { layout0.marginWidth = 5; layout0.marginHeight = 4; pageComponent.setLayout(layout0); - GridData data0 = new GridData(GridData.FILL_HORIZONTAL); - data0.widthHint = 640; - pageComponent.setLayoutData(data0); - pageComponent.setFont(parent.getFont()); + GridData gridData0 = new GridData(GridData.FILL_HORIZONTAL); + gridData0.widthHint = 640; + pageComponent.setLayoutData(gridData0); + pageComponent.setFont(font); // define group1 Group pageGroup1 = new Group(pageComponent, SWT.SHADOW_ETCHED_IN); pageGroup1.setText(Activator.getResourceString("easyshell.menu.editor.dialog.title")); @@ -88,15 +95,39 @@ public Control createDialogArea(Composite parent) { layout1.marginWidth = 5; layout1.marginHeight = 4; pageGroup1.setLayout(layout1); - GridData data1 = new GridData(GridData.FILL_HORIZONTAL); - pageGroup1.setLayoutData(data1); - pageGroup1.setFont(parent.getFont()); + GridData gridData1 = new GridData(GridData.FILL_HORIZONTAL); + pageGroup1.setLayoutData(gridData1); + pageGroup1.setFont(font); // create activity checkbox createEnabledCheckBox(pageGroup1); // create selected command combo createCommandCombo(pageGroup1); //create input nameText field commandText = createTextField(pageGroup1, Activator.getResourceString("easyshell.menu.editor.dialog.command.label"), data.getCommandData().getCommand(), false); + // buttons + addButton = new Button(pageGroup1, SWT.PUSH); + addButton.setText(Activator.getResourceString("easyshell.page.table.button.add")); //$NON-NLS-1$ + addButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + add(); + } + }); + addButton.setLayoutData(gridData1); + addButton.setFont(font); + setButtonLayoutData(addButton); + editButton = new Button(pageGroup1, SWT.PUSH); + editButton.setText(Activator.getResourceString("easyshell.page.table.button.edit")); //$NON-NLS-1$ + editButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + edit(); + } + }); + editButton.setLayoutData(gridData1); + editButton.setFont(font); + setButtonLayoutData(editButton); + //create input nameText field nameText = createTextField(pageGroup1, Activator.getResourceString("easyshell.menu.editor.dialog.name.label"), data.getName(), true); @@ -115,11 +146,53 @@ protected void okPressed() { return; } data.setEnabled(enabledCheckBox.getSelection()); - data.setCommandData(cmdList.get(commandCombo.getSelectionIndex())); + data.setCommandData(cmdList.get(commandCombo.getSelectionIndex()), false); data.setName(nameText.getText()); super.okPressed(); } + private void add() { + CommandData data = new CommandData(); + CommandDataDialog dialog = new CommandDataDialog(getShell(), data, false); + if (dialog.open() == Window.OK) { + cmdStore.add(data); + cmdStore.save(); + cmdList.add(data); + String[] names = getAllCommandsAsComboNames(cmdList); + commandCombo.setItems(names); + commandCombo.select(names.length-1); + // send event to refresh + Event event = new Event(); + event.item = null; + commandCombo.notifyListeners(SWT.Selection, event); + /* + tableViewer.refresh(); + tableViewer.setChecked(data, data.isEnabled()); + tableViewer.setSelection(new StructuredSelection(data)); + */ + return; + } + } + + private void edit() { + int index = commandCombo.getSelectionIndex(); + CommandData data = cmdList.get(index); + CommandDataDialog dialog = new CommandDataDialog(getShell(), data, true); + if (dialog.open() == Window.OK) { + commandCombo.setItem(index, getCommandAsComboName(data)); + // send event to refresh + Event event = new Event(); + event.item = null; + commandCombo.notifyListeners(SWT.Selection, event); + /* + tableViewer.refresh(); + tableViewer.setChecked(data, data.isEnabled()); + tableViewer.setSelection(new StructuredSelection(data)); + */ + return; + } + } + private boolean validateValues() { final String title = Activator.getResourceString("easyshell.menu.editor.dialog.error.incompletedata.title"); @@ -159,11 +232,14 @@ private void createEnabledCheckBox(Composite parent) { } } + private String getCommandAsComboName(CommandData data) { + return data.getOS().getName() + " - " + data.getCommandType().getName() + " - " + data.getName(); + } + private String[] getAllCommandsAsComboNames(List list) { String[] arr = new String[list.size()]; for (int i=0;i Date: Tue, 12 Jul 2016 23:13:08 +0200 Subject: [PATCH 05/73] added buttons to menu and command dialogs (New, Copy, Edit, Remove) - added confirmation dialogs - added PresetType - added double-click handling for variables - added tool-tips - refactoring of class names - moved to statics to new Utils class Signed-off-by: Andre Bossert --- .../easyshell/plugin/UIMessages.properties | 74 ++++-- .../plugin/actions/ActionDelegate.java | 14 +- .../plugin/commands/DefineCommands.java | 10 +- .../plugin/preferences/CommandData.java | 35 ++- .../CommandDataDefaultCollection.java | 239 +++--------------- .../plugin/preferences/CommandDataDialog.java | 128 ++++++---- .../plugin/preferences/CommandsPage.java | 223 ++++++++++------ .../{CommandMenuData.java => MenuData.java} | 17 +- ...ider.java => MenuDataContentProvider.java} | 8 +- ...enuDataDialog.java => MenuDataDialog.java} | 233 +++++++++++------ ...ovider.java => MenuDataLabelProvider.java} | 10 +- ...dMenuDataMover.java => MenuDataMover.java} | 16 +- ...dMenuDataStore.java => MenuDataStore.java} | 76 +++--- .../preferences/PreferenceValueConverter.java | 14 +- .../plugin/preferences/PresetType.java | 72 ++++++ .../easyshell/plugin/preferences/Utils.java | 207 +++++++++++++++ 16 files changed, 858 insertions(+), 518 deletions(-) rename plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/{CommandMenuData.java => MenuData.java} (90%) rename plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/{CommandMenuDataContentProvider.java => MenuDataContentProvider.java} (80%) rename plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/{CommandMenuDataDialog.java => MenuDataDialog.java} (55%) rename plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/{CommandMenuDataLabelProvider.java => MenuDataLabelProvider.java} (82%) rename plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/{CommandMenuDataMover.java => MenuDataMover.java} (78%) rename plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/{CommandMenuDataStore.java => MenuDataStore.java} (60%) create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetType.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Utils.java diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties index b548cfb5..c9c862db 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties @@ -2,31 +2,55 @@ easyshell.plugin.name=EasyShell easyshell.properties.main.page.title=EasyShell easyshell.properties.commands.page.title=Presets easyshell.actionset.name=EasyShell +easyshell.message.copytoclipboard=copied to clipboard -easyshell.page.table.header.column0.title=Name -easyshell.page.table.header.column1.title=Command -easyshell.page.table.button.add=Add... -easyshell.page.table.button.edit=Edit... -easyshell.page.table.button.remove=Remove -easyshell.page.table.button.up=Up -easyshell.page.table.button.down=Down +easyshell.page.table.header.title.column0=Name +easyshell.page.table.header.title.column1=Command +easyshell.page.table.button.text.new=Add... +easyshell.page.table.button.tooltip.new=Add new menu +easyshell.page.table.button.text.copy=Copy... +easyshell.page.table.button.tooltip.copy=Copy selected menu as new menu +easyshell.page.table.button.text.edit=Edit... +easyshell.page.table.button.tooltip.edit=Edit selected menu +easyshell.page.table.button.text.remove=Remove... +easyshell.page.table.button.tooltip.remove=Remove selected menu(s) +easyshell.page.table.button.text.up=Up +easyshell.page.table.button.tooltip.up=Move selected menu up +easyshell.page.table.button.text.down=Down +easyshell.page.table.button.tooltip.down=Move selected menu down +easyshell.page.table.dialog.remove.title=Remove menu(s) +easyshell.page.table.dialog.remove.question=Do you really want to remove selected menu(s) ? -easyshell.command.editor.dialog.new.title=Create new command -easyshell.command.editor.dialog.edit.title=Edit existing command -easyshell.command.editor.dialog.title=Command definition -easyshell.command.editor.dialog.error.incompletedata.title=Missing or wrong command detected -easyshell.command.editor.dialog.error.type.text=Please choose a type -easyshell.command.editor.dialog.error.name.text=Please enter a valid name -easyshell.command.editor.dialog.error.value.text=Please enter a valid command -easyshell.command.editor.dialog.combo.label=type: -easyshell.command.editor.dialog.name.label=name: -easyshell.command.editor.dialog.value.label=command: +easyshell.menu.editor.dialog.title.new=Create new menu +easyshell.menu.editor.dialog.title.edit=Edit existing menu +easyshell.menu.editor.dialog.title.group1=Menu definition +easyshell.menu.editor.dialog.error.text.name=Please enter a valid name +easyshell.menu.editor.dialog.error.type.text=Please choose a valid type +easyshell.menu.editor.dialog.label.active=enabled: +easyshell.menu.editor.dialog.label.name=menu name: +easyshell.menu.editor.dialog.label.combo=preset: +easyshell.menu.editor.dialog.label.command=command: +easyshell.menu.editor.dialog.button.text.new=New... +easyshell.menu.editor.dialog.button.tooltip.new=Add new user command +easyshell.menu.editor.dialog.button.text.copy=Copy... +easyshell.menu.editor.dialog.button.tooltip.copy=Copy selected command as user command +easyshell.menu.editor.dialog.button.text.edit=Edit... +easyshell.menu.editor.dialog.button.tooltip.edit=Edit selected user command +easyshell.menu.editor.dialog.button.text.remove=Remove... +easyshell.menu.editor.dialog.button.tooltip.remove=Remove selected user command +easyshell.menu.editor.dialog.title.remove=Remove user command +easyshell.menu.editor.dialog.question.remove=Do you really want to remove user command "{0}" ? -easyshell.menu.editor.dialog.new.title=Create new menu -easyshell.menu.editor.dialog.edit.title=Edit existing menu -easyshell.menu.editor.dialog.title=Menu definition -easyshell.menu.editor.dialog.error.name.text=Please enter a valid name -easyshell.menu.editor.dialog.active.label=enabled: -easyshell.menu.editor.dialog.name.label=menu name: -easyshell.menu.editor.dialog.combo.label=preset: -easyshell.menu.editor.dialog.command.label=command: +easyshell.command.editor.dialog.title.new=Create new command +easyshell.command.editor.dialog.title.edit=Edit existing command +easyshell.command.editor.dialog.title.group1=Command definition +easyshell.command.editor.dialog.tooltip.group1=Add your command here +easyshell.command.editor.dialog.title.group2=Usable variables +easyshell.command.editor.dialog.tooltip.group2=Double click at variables to copy them to clipboard +easyshell.command.editor.dialog.error.title.incompletedata=Missing or wrong command detected +easyshell.command.editor.dialog.error.text.type=Please choose a valid type +easyshell.command.editor.dialog.error.text.name=Please enter a valid name +easyshell.command.editor.dialog.error.text.value=Please enter a valid command +easyshell.command.editor.dialog.label.combo=type: +easyshell.command.editor.dialog.label.name=name: +easyshell.command.editor.dialog.label.value=command: diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java index d5d560a3..7e3e9eef 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java @@ -19,19 +19,18 @@ import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.swt.dnd.Clipboard; -import org.eclipse.swt.dnd.TextTransfer; -import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IObjectActionDelegate; import org.eclipse.ui.IWorkbenchPart; +import de.anbos.eclipse.easyshell.plugin.Activator; import de.anbos.eclipse.easyshell.plugin.DynamicVariableResolver; import de.anbos.eclipse.easyshell.plugin.Resource; import de.anbos.eclipse.easyshell.plugin.ResourceUtils; import de.anbos.eclipse.easyshell.plugin.preferences.CommandType; import de.anbos.eclipse.easyshell.plugin.preferences.Quotes; +import de.anbos.eclipse.easyshell.plugin.preferences.Utils; public class ActionDelegate implements IObjectActionDelegate { @@ -156,6 +155,7 @@ public void run(IAction action) { c++; } //Activator.getDefault().sysout(true, "--- cmd: <"); + //Utils.showToolTip(Display.getDefault().getActiveShell(), "EasyShell: executed", target); Runtime.getRuntime().exec(cmds); } // the old command line passing without string tokenizer @@ -186,12 +186,8 @@ public void run(IAction action) { // handling copy to clipboard if ((commandType == CommandType.commandTypeClipboard) && (cmdAll != null) && (cmdAll.length() != 0)) { - Clipboard clipboard = new Clipboard(Display.getCurrent()); - TextTransfer textTransfer = TextTransfer.getInstance(); - Transfer[] transfers = new Transfer[]{textTransfer}; - Object[] data = new Object[]{cmdAll}; - clipboard.setContents(data, transfers); - clipboard.dispose(); + Utils.copyToClipboard(cmdAll); + Utils.showToolTip(Display.getDefault().getActiveShell(), Activator.getResourceString("easyshell.plugin.name") + ": " + Activator.getResourceString("easyshell.message.copytoclipboard"), cmdAll); } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java index 94e4844f..82f7f442 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java @@ -23,8 +23,8 @@ import org.eclipse.ui.services.IServiceLocator; import de.anbos.eclipse.easyshell.plugin.Activator; -import de.anbos.eclipse.easyshell.plugin.preferences.CommandMenuData; -import de.anbos.eclipse.easyshell.plugin.preferences.CommandMenuDataStore; +import de.anbos.eclipse.easyshell.plugin.preferences.MenuData; +import de.anbos.eclipse.easyshell.plugin.preferences.MenuDataStore; public class DefineCommands extends ExtensionContributionFactory { @@ -36,10 +36,10 @@ public void createContributionItems(IServiceLocator serviceLocator, IContributionRoot additions) { // load the preferences - CommandMenuDataStore store = new CommandMenuDataStore(Activator.getDefault().getPreferenceStore()); + MenuDataStore store = new MenuDataStore(Activator.getDefault().getPreferenceStore()); store.load(); - List items = store.getEnabledCommandMenuDataList(); - for (CommandMenuData item : items) { + List items = store.getEnabledCommandMenuDataList(); + for (MenuData item : items) { addItem(serviceLocator, additions, item.getName(), "de.anbos.eclipse.easyshell.plugin.commands.execute", diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java index 61662244..6b8ec016 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java @@ -20,13 +20,15 @@ public class CommandData { private int position = 0; private String id = UUID.randomUUID().toString(); // command - private OS os = OS.osWindows; - private String name = "Name"; + private PresetType presetType = PresetType.presetUser; + private OS os = OS.osUnknown; + private String name = "MyNewCommand"; private RessourceType resType = RessourceType.ressourceFileOrFolder; - private CommandType cmdType = CommandType.commandTypeOpen; - private String command = "command"; + private CommandType cmdType = CommandType.commandTypeOther; + private String command = "my_new_command"; - public CommandData(OS os, String name, RessourceType resType, CommandType cmdType, String command) { + public CommandData(PresetType presetType, OS os, String name, RessourceType resType, CommandType cmdType, String command) { + this.presetType = presetType; this.os = os; this.name = name; this.resType = resType; @@ -34,6 +36,15 @@ public CommandData(OS os, String name, RessourceType resType, CommandType cmdTyp this.command = command; } + public CommandData(CommandData commandData) { + this.presetType = commandData.getPresetType(); + this.os = commandData.getOS(); + this.name = commandData.getName(); + this.resType = commandData.getRessourceType(); + this.cmdType = commandData.getCommandType(); + this.command = commandData.getCommand(); + } + public CommandData() { } @@ -53,6 +64,10 @@ public OS getOS() { return os; } + public PresetType getPresetType() { + return presetType; + } + public RessourceType getRessourceType() { return resType; } @@ -81,6 +96,10 @@ public void setOs(OS os) { this.os = os; } + public void setPresetType(PresetType presetType) { + this.presetType = presetType; + } + public void setRessourceType(RessourceType resType) { this.resType = resType; } @@ -101,6 +120,7 @@ public boolean equals(Object object) { if(data.getPosition() == this.getPosition() && data.getName().equals(this.getName()) && data.getOS() == this.getOS() && + data.getPresetType() == this.getPresetType() && data.getRessourceType() == this.getRessourceType() && data.getCommandType() == this.getCommandType() && data.getCommand().equals(this.getCommand() @@ -122,8 +142,9 @@ public boolean deserialize(String value, StringTokenizer tokenizer, String delim // set members setPosition(Integer.parseInt(tokenizer.nextToken())); setId(tokenizer.nextToken()); + setPresetType(PresetType.getFromEnum(tokenizer.nextToken())); + setOs(OS.getFromEnum(tokenizer.nextToken())); setName(tokenizer.nextToken()); - setOs(OS.getFromEnum(tokenizer.nextToken())); setRessourceType(RessourceType.getFromEnum(tokenizer.nextToken())); setCommandType(CommandType.getFromEnum(tokenizer.nextToken())); setCommand(tokenizer.nextToken()); @@ -131,7 +152,7 @@ public boolean deserialize(String value, StringTokenizer tokenizer, String delim } public String serialize(String delimiter) { - return Integer.toString(getPosition()) + delimiter + getId() + delimiter + getName() + delimiter + getOS().toString() + delimiter + getRessourceType().toString() + delimiter + getCommandType().toString() + delimiter + getCommand() + delimiter; + return Integer.toString(getPosition()) + delimiter + getId() + delimiter + getPresetType().toString() + delimiter + getOS().toString() + delimiter + getName() + delimiter + getRessourceType().toString() + delimiter + getCommandType().toString() + delimiter + getCommand() + delimiter; } public String getTypeIcon() { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java index 9b8bae10..78bc7a25 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java @@ -11,12 +11,8 @@ package de.anbos.eclipse.easyshell.plugin.preferences; -import java.io.BufferedReader; -import java.io.InputStreamReader; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; public class CommandDataDefaultCollection { @@ -31,98 +27,98 @@ public static List getDefaultCommandsStatic() { return getDefaultCommands(); } - public static List getDefaultCommandsMenuStatic() { + public static List getDefaultCommandsMenuStatic() { List list = getDefaultCommandsStatic(); - List ret = new ArrayList(); + List ret = new ArrayList(); for (CommandData data : list) { - ret.add(new CommandMenuData(data)); + ret.add(new MenuData(data)); } return ret; } CommandDataDefaultCollection() { // Windows DOS-Shell - list.add(new CommandData(OS.osWindows, "DOS-Shell", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "DOS-Shell", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} cmd.exe /K")); - list.add(new CommandData(OS.osWindows, "DOS-Shell", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "DOS-Shell", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} ${easyshell:resource_name}")); // Windows Explorer - list.add(new CommandData(OS.osWindows, "Explorer", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Explorer", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, "explorer.exe /select, ${easyshell:resource_loc}")); // Windows PowerShell - list.add(new CommandData(OS.osWindows, "PowerShell", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "PowerShell", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} powershell.exe")); - list.add(new CommandData(OS.osWindows, "PowerShell", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "PowerShell", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} powershell.exe -command ./''${easyshell:resource_name}''")); // Windows Cygwin (Bash) - list.add(new CommandData(OS.osWindows, "Cygwin (Bash)", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Cygwin\\bin\\bash.exe\"")); - list.add(new CommandData(OS.osWindows, "Cygwin (Bash)", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Cygwin\\bin\\bash.exe\" -c ./''${easyshell:resource_name}''")); // Windows Console - list.add(new CommandData(OS.osWindows, "Console", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Console", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, "console.exe -w \"${easyshell:project_name}\" -d ${easyshell:container_loc}")); - list.add(new CommandData(OS.osWindows, "Cygwin (Bash)", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, "console.exe -w \"${easyshell:project_name}\" -d ${easyshell:container_loc} -r \"/k\\\"${easyshell:resource_name}\\\"\"")); // Windows Git-Bash - list.add(new CommandData(OS.osWindows, "Git-Bash", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Git-Bash", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Program Files (x86)\\Git\\bin\\bash.exe\" --login -i")); - list.add(new CommandData(OS.osWindows, "Cygwin (Bash)", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Program Files (x86)\\Git\\bin\\bash.exe\" --login -i -c ./''${easyshell:resource_name}''")); // Windows ConEmu - list.add(new CommandData(OS.osWindows, "ConEmu", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "ConEmu", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, "ConEmu.exe /Title \"${easyshell:project_name}\" /Dir \"${easyshell:container_loc}\" /Single /cmd cmd")); - list.add(new CommandData(OS.osWindows, "Cygwin (Bash)", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, "ConEmu.exe /Title \"${easyshell:project_name}\" /Dir \"${easyshell:container_loc}\" /Single /cmd \"${easyshell:resource_name}\"")); // Windows TotalCommander - list.add(new CommandData(OS.osWindows, "TotalCommander", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "TotalCommander", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, "totalcmd.exe /O /T ${easyshell:container_loc}")); // Windows Clipboard - list.add(new CommandData(OS.osWindows, "Full path", RessourceType.ressourceFileOrFolder, CommandType.commandTypeClipboard, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Full path", RessourceType.ressourceFileOrFolder, CommandType.commandTypeClipboard, "\"${easyshell:resource_loc}\"${easyshell:line_separator}")); // Linux KDE Konsole - list.add(new CommandData(OS.osLinux, "KDE Konsole", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "KDE Konsole", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, "konsole --workdir ${easyshell:container_loc}")); - list.add(new CommandData(OS.osLinux, "KDE Konsole", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "KDE Konsole", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, "konsole --workdir ${easyshell:container_loc} --noclose -e ${easyshell:resource_loc}")); // Linux Konqueror - list.add(new CommandData(OS.osLinux, "Konqueror", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Konqueror", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, "konqueror file:\"${easyshell:resource_loc}\"")); // Linux Gnome Terminal - list.add(new CommandData(OS.osLinux, "Gnome Terminal", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Gnome Terminal", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, "gnome-terminal --working-directory=${easyshell:container_loc}")); - list.add(new CommandData(OS.osLinux, "Gnome Terminal", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Gnome Terminal", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, "gnome-terminal --working-directory=${easyshell:container_loc} --command=./''${easyshell:resource_name}''")); // Linux Xfce Terminal - list.add(new CommandData(OS.osLinux, "Xfce Terminal", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Xfce Terminal", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, "xfce4-terminal --working-directory=${easyshell:container_loc}")); - list.add(new CommandData(OS.osLinux, "Xfce Terminal", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Xfce Terminal", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, "xfce4-terminal --working-directory=${easyshell:container_loc} --command=./''${easyshell:resource_name}'' --hold")); // Linux Nautilus - list.add(new CommandData(OS.osLinux, "Nautilus", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Nautilus", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, "nautilus ${easyshell:resource_loc}")); // Linux Dolphin - list.add(new CommandData(OS.osLinux, "Dolphin", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Dolphin", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, "dolphin --select ${easyshell:resource_loc}")); // Linux Nemo - list.add(new CommandData(OS.osLinux, "Nemo", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Nemo", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, "nemo ${easyshell:resource_loc}")); // Linux Thunar - list.add(new CommandData(OS.osLinux, "Thunar", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Thunar", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, "thunar ${easyshell:resource_loc}")); // Linux Clipboard - list.add(new CommandData(OS.osLinux, "Full path", RessourceType.ressourceFileOrFolder, CommandType.commandTypeClipboard, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Full path", RessourceType.ressourceFileOrFolder, CommandType.commandTypeClipboard, "${easyshell:resource_loc}${easyshell:line_separator}")); // MAC OS X Terminal - list.add(new CommandData(OS.osMacOSX, "Terminal", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osMacOSX, "Terminal", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, "open -a Terminal ${easyshell:container_loc}")); - list.add(new CommandData(OS.osMacOSX, "Terminal", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osMacOSX, "Terminal", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, "open -a Terminal ${easyshell:container_loc}")); // MAC OS X Finder - list.add(new CommandData(OS.osMacOSX, "Finder", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, + list.add(new CommandData(PresetType.presetPlugin, OS.osMacOSX, "Finder", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, "open -R ${easyshell:resource_loc}")); // MAC OS X Clipboard - list.add(new CommandData(OS.osMacOSX, "Full path", RessourceType.ressourceFileOrFolder, CommandType.commandTypeClipboard, + list.add(new CommandData(PresetType.presetPlugin, OS.osMacOSX, "Full path", RessourceType.ressourceFileOrFolder, CommandType.commandTypeClipboard, "${easyshell:resource_loc}${easyshell:line_separator}")); } @@ -134,14 +130,14 @@ public static List getCommandsNative(List list) { if (list == null) { list = getAllCommandsStatic(); } - return getCommandData(list, getOS()); + return getCommandData(list, Utils.getOS()); } public static List getDefaultCommands() { List listAll = getAllCommandsStatic(); List listOS = new ArrayList(); List listDefault = new ArrayList(); - OS os = getOS(); + OS os = Utils.getOS(); // now get all data by OS listOS = getCommandData(listAll, os); // now get by name @@ -156,7 +152,7 @@ public static List getDefaultCommands() { break; case osLinux: // try to detect the desktop - LinuxDesktop desktop = detectLinuxDesktop(); + LinuxDesktop desktop = Utils.detectLinuxDesktop(); //Activator.getDefault().sysout(true, "Detected linux (Unix) desktop: >" + desktop.getName() + "<"); switch (desktop) { case desktopKde: listDefault.add(getCommandData(listOS, "KDE", CommandType.commandTypeOpen)); @@ -179,7 +175,7 @@ public static List getDefaultCommands() { } // try to detect the default file browser if (desktop != LinuxDesktop.desktopUnknown) { - String fileBrowser = detectLinuxDefaultFileBrowser(); + String fileBrowser = Utils.detectLinuxDefaultFileBrowser(); //Activator.getDefault().sysout(true, "Detected linux (Unix) default file browser: >" + fileBrowser + "<"); } break; @@ -194,52 +190,6 @@ public static List getDefaultCommands() { return listDefault; } - public static OS getOS() { - OS os = OS.osUnknown; - /* possible OS string: - AIX - Digital UNIX - FreeBSD - HP UX - Irix - Linux - Mac OS - Mac OS X - MPE/iX - Netware 4.11 - OS/2 - Solaris - Windows 95 - Windows 98 - Windows NT - Windows Me - Windows 2000 - Windows XP - Windows 2003 - Windows CE - Windows Vista - Windows 7 - */ - String osname = System.getProperty("os.name", "").toLowerCase(); - if (osname.indexOf("windows") != -1) { - os = OS.osWindows; - } else if (osname.indexOf("mac os x") != -1) { - os = OS.osMacOSX; - } else if ( - osname.indexOf("unix") != -1 - || osname.indexOf("irix") != -1 - || osname.indexOf("freebsd") != -1 - || osname.indexOf("hp-ux") != -1 - || osname.indexOf("aix") != -1 - || osname.indexOf("sunos") != -1 - || osname.indexOf("linux") != -1 - ) - { - os = OS.osLinux; - } - return os; - } - public static List getCommandData(List list, OS os) { List listOut = new ArrayList(); for (CommandData entry : list) { @@ -259,117 +209,4 @@ private static CommandData getCommandData(List list, String name, C return null; } - private static LinuxDesktop detectLinuxDesktop() { - LinuxDesktop resultCode = detectDesktopSession(); - /* - if (resultCode == LinuxDesktop.desktopUnknown) - { - if (isCde()) - resultCode = LinuxDesktop.desktopCde; - } - */ - return resultCode; - } - - /** - * detects desktop from $DESKTOP_SESSION - */ - private static LinuxDesktop detectDesktopSession() { - ArrayList command = new ArrayList(); - command.add("sh"); - command.add("-c"); - command.add("echo \"$DESKTOP_SESSION\""); - // fill the map - Map desktops = new HashMap(); - desktops.put("kde", LinuxDesktop.desktopKde); - desktops.put("gnome", LinuxDesktop.desktopGnome); - desktops.put("cinnamon", LinuxDesktop.desktopCinnamon); - desktops.put("xfce", LinuxDesktop.desktopXfce); - // execute - String desktop = isExpectedCommandOutput(command, desktops, true); - if (desktop != null && !desktop.isEmpty()) { - return (LinuxDesktop)desktops.get(desktop); - } - return LinuxDesktop.desktopUnknown; - } - - /** - * detects programs from $DESKTOP_SESSION - */ - private static String detectLinuxDefaultFileBrowser() { - ArrayList command = new ArrayList(); - command.add("xdg-mime"); - command.add("query"); - command.add("default"); - command.add("inode/directory"); - // fill the map - Map fileBrowsers = new HashMap(); - fileBrowsers.put("nemo.desktop", "nemo"); - // execute - String fileBrowser = isExpectedCommandOutput(command, fileBrowsers, true); - if (fileBrowser != null && !fileBrowser.isEmpty()) { - return (String)fileBrowsers.get(fileBrowser); - } - return null; - } - - /** - * Detects which desktop is used on a unix / linux system. - * - * @todo use regex - * - * @return The type of desktop. - * @see detectDesktop - */ - private static String isExpectedCommandOutput(ArrayList command, Map expectedOutput, boolean toLowerCase) { - boolean found = false; - String expectedLine = null; - try { - Process proc = Runtime.getRuntime().exec(command.toArray(new String[1])); - BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream())); - String line = null; - while((line = in.readLine()) != null && !found) { - for(String key: expectedOutput.keySet()) { - // in case of * just something should be returned - if (key.indexOf("*") != -1) - { - if (line.isEmpty()) { - found = false; - break; - } else { - found = true; - } - } else { - if (toLowerCase) - line = line.toLowerCase(); - if(line.indexOf(key) != -1) { - found = true; - } - } - if (found) { - expectedLine = line; - break; - } - } - } - line = null; - BufferedReader err = new BufferedReader(new InputStreamReader(proc.getErrorStream())); - // If there is any error output, print it to - // stdout for debugging purposes - while((line = err.readLine()) != null) { - //Activator.getDefault().sysout(true, "detectDesktop stderr >" + line + "<"); - } - - int result = proc.waitFor(); - if(result != 0) { - // If there is any error code, print it to - // stdout for debugging purposes - //Activator.getDefault().sysout(true, "detectDesktop return code: " + result); - } - } catch(Exception e) { - e.printStackTrace(); - } - return expectedLine; - } - } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java index 9741519b..26ffda16 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java @@ -17,6 +17,9 @@ import org.eclipse.jface.dialogs.StatusDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CCombo; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; @@ -34,7 +37,6 @@ public class CommandDataDialog extends StatusDialog { private CommandData data; - private boolean edit; private Text nameText; private CCombo typeCombo; @@ -43,15 +45,14 @@ public class CommandDataDialog extends StatusDialog { public CommandDataDialog(Shell parent, CommandData data, boolean edit) { super(parent); this.data = data; - this.edit = edit; // do layout and title setShellStyle(getShellStyle() | SWT.MAX); // set title String title = null; if(edit) { - title = Activator.getResourceString("easyshell.command.editor.dialog.edit.title"); //$NON-NLS-1$ + title = Activator.getResourceString("easyshell.command.editor.dialog.title.edit"); } else { - title = Activator.getResourceString("easyshell.command.editor.dialog.new.title"); //$NON-NLS-1$ + title = Activator.getResourceString("easyshell.command.editor.dialog.title.new"); } setTitle(title); } @@ -75,7 +76,8 @@ public Control createDialogArea(Composite parent) { pageComponent.setFont(parent.getFont()); // define group1 Group pageGroup1 = new Group(pageComponent, SWT.SHADOW_ETCHED_IN); - pageGroup1.setText(Activator.getResourceString("easyshell.command.editor.dialog.title")); + pageGroup1.setText(Activator.getResourceString("easyshell.command.editor.dialog.title.group1")); + pageGroup1.setToolTipText(Activator.getResourceString("easyshell.command.editor.dialog.tooltip.group1")); GridLayout layout1 = new GridLayout(); layout1.numColumns = 2; layout1.makeColumnsEqualWidth = false; @@ -88,34 +90,80 @@ public Control createDialogArea(Composite parent) { // create type type combo createTypeCombo(pageGroup1); //create input nameText field - nameText = createTextField(pageGroup1, Activator.getResourceString("easyshell.command.editor.dialog.name.label"), data.getName()); + nameText = createTextField(pageGroup1, Activator.getResourceString("easyshell.command.editor.dialog.label.name"), data.getName()); // create input valueText field - valueText = createTextField(pageGroup1, Activator.getResourceString("easyshell.command.editor.dialog.value.label"), data.getCommand()); + valueText = createTextField(pageGroup1, Activator.getResourceString("easyshell.command.editor.dialog.label.value"), data.getCommand()); // ------------------------------------ Description ------------------------------------------ - Label desc_label = new Label(pageComponent, 0); - desc_label.setText("${easyshell:drive} is the drive letter on Win32"); - desc_label = new Label(pageComponent, 0); - desc_label.setText("${easyshell:container_loc} is the parent path*"); - desc_label = new Label(pageComponent, 0); - desc_label.setText("${easyshell:resource_loc} is the full path*"); - desc_label = new Label(pageComponent, 0); - desc_label.setText("${easyshell:resource_name} is the file name*"); - desc_label = new Label(pageComponent, 0); - desc_label.setText("${easyshell:project_name} is the project name"); - desc_label = new Label(pageComponent, 0); - desc_label.setText("${easyshell:line_separator} is the line separator"); - - //if (edit) { - // send event to refresh - Event event = new Event(); - event.item = null; - typeCombo.notifyListeners(SWT.Selection, event); - //} + // define group2 + Group pageGroup2 = new Group(pageComponent, SWT.SHADOW_ETCHED_IN); + pageGroup2.setText(Activator.getResourceString("easyshell.command.editor.dialog.title.group2")); + pageGroup2.setToolTipText(Activator.getResourceString("easyshell.command.editor.dialog.tooltip.group2")); + GridLayout layout2 = new GridLayout(); + layout2.numColumns = 2; + layout2.makeColumnsEqualWidth = false; + layout2.marginWidth = 5; + layout2.marginHeight = 4; + pageGroup2.setLayout(layout2); + GridData data2 = new GridData(GridData.FILL_HORIZONTAL); + pageGroup2.setLayoutData(data2); + pageGroup2.setFont(parent.getFont()); + + createLabel(pageGroup2, "${easyshell:drive}", "is the drive letter on Win32"); + createLabel(pageGroup2, "${easyshell:container_loc}", "is the parent path*"); + createLabel(pageGroup2, "${easyshell:resource_loc}", "is the full path*"); + createLabel(pageGroup2, "${easyshell:resource_name}", "is the file name*"); + createLabel(pageGroup2, "${easyshell:project_name}", "is the project name"); + createLabel(pageGroup2, "${easyshell:line_separator}", "is the line separator"); + + refreshTypeCombo(); return pageComponent; } + private void createLabel(Composite parent, String varText, String labelText) { + StyledText styledTextWidget = new StyledText(parent, SWT.NONE); + styledTextWidget.setText(varText); + styledTextWidget.setBackground(parent.getBackground()); + styledTextWidget.setEditable(false); + styledTextWidget.setCaret(null); //Set caret null this will hide caret + styledTextWidget.addMouseListener(new MouseListener() { + + @Override + public void mouseUp(MouseEvent e) { + // TODO Auto-generated method stub + + } + + @Override + public void mouseDown(MouseEvent e) { + // TODO Auto-generated method stub + + } + + @Override + public void mouseDoubleClick(MouseEvent e) { + StyledText text = (StyledText)(e.getSource()); + Control control = text; + text.selectAll(); + String title = Activator.getResourceString("easyshell.message.copytoclipboard"); + String message = text.getText(); + Utils.copyToClipboard(title); + Utils.showToolTip(control, title, message); + text.setSelection(0, 0); + } + }); + Label label = new Label(parent, 0); + label.setText(labelText); + } + + private void refreshTypeCombo() { + // send event to refresh + Event event = new Event(); + event.item = null; + typeCombo.notifyListeners(SWT.Selection, event); + } + protected void okPressed() { if (!validateValues()) { return; @@ -128,25 +176,25 @@ protected void okPressed() { private boolean validateValues() { - final String title = Activator.getResourceString("easyshell.command.editor.dialog.error.incompletedata.title"); + final String title = Activator.getResourceString("easyshell.command.editor.dialog.error.title.incompletedata"); // check type if ( (typeCombo.getText() == null) || (typeCombo.getText().length() <= 0)) { - MessageDialog.openError(getShell(), title, Activator.getResourceString("easyshell.command.editor.dialog.error.type.text")); + MessageDialog.openError(getShell(), title, Activator.getResourceString("easyshell.command.editor.dialog.error.text.type")); return false; } boolean valid = true; // check name - String text = Activator.getResourceString("easyshell.command.editor.dialog.error.name.text"); + String text = Activator.getResourceString("easyshell.command.editor.dialog.error.text.name"); if ( (nameText.getText() == null) || (nameText.getText().length() <= 0)) { valid = false; } // check value if (valid) { - text = Activator.getResourceString("easyshell.command.editor.dialog.error.value.text"); + text = Activator.getResourceString("easyshell.command.editor.dialog.error.text.value"); if ( (valueText.getText() == null) || (valueText.getText().length() <= 0)) { valid = false; } @@ -172,7 +220,7 @@ private void createTypeCombo(Composite parent) { // draw label Label comboLabel = new Label(parent,SWT.LEFT); comboLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END)); - comboLabel.setText(Activator.getResourceString("easyshell.command.editor.dialog.combo.label")); //$NON-NLS-1$ + comboLabel.setText(Activator.getResourceString("easyshell.command.editor.dialog.label.combo")); // draw combo typeCombo = new CCombo(parent,SWT.BORDER); typeCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); @@ -189,16 +237,12 @@ public void widgetDefaultSelected(SelectionEvent e) { // TODO Auto-generated method stub } }); - if(edit) { - String[] items = typeCombo.getItems(); - for(int i = 0 ; i < items.length ; i++) { - if(items[i].equals(this.data.getCommandType().getName())) { - typeCombo.select(i); - return; - } + String[] items = typeCombo.getItems(); + for(int i = 0 ; i < items.length ; i++) { + if(items[i].equals(this.data.getCommandType().getName())) { + typeCombo.select(i); + return; } - } else { - typeCombo.select(0); } } @@ -210,9 +254,7 @@ private Text createTextField(Composite parent, String labelText, String editValu // draw textfield Text text = new Text(parent,SWT.BORDER); text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - if(edit) { - text.setText(editValue); - } + text.setText(editValue); return text; } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsPage.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsPage.java index 1cc065fa..1caa55da 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsPage.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsPage.java @@ -11,10 +11,12 @@ package de.anbos.eclipse.easyshell.plugin.preferences; +import java.text.MessageFormat; import java.util.Iterator; import java.util.List; import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.CheckStateChangedEvent; import org.eclipse.jface.viewers.CheckboxTableViewer; import org.eclipse.jface.viewers.DoubleClickEvent; @@ -52,12 +54,13 @@ public class CommandsPage extends org.eclipse.jface.preference.PreferencePage private static final int TABLE_WIDTH = 400; private Table table; - private CommandMenuDataMover itemMover; + private MenuDataMover itemMover; private CommandDataStore cmdStore; List cmdList; - private CommandMenuDataStore menuStore; + private MenuDataStore menuStore; private CheckboxTableViewer tableViewer; - private Button addButton; + private Button addNewButton; + private Button addCopyButton; private Button editButton; private Button upButton; private Button downButton; @@ -77,7 +80,7 @@ public boolean performOk() { protected void performDefaults() { menuStore.loadDefaults(); tableViewer.refresh(); - for (CommandMenuData item : menuStore.getCommandMenuDataList()) { + for (MenuData item : menuStore.getCommandMenuDataList()) { tableViewer.setChecked(item, true); } } @@ -107,11 +110,11 @@ protected Control createContents(Composite parent) { table.setFont(parent.getFont()); TableColumn column1 = new TableColumn(table, SWT.LEFT); - column1.setText(Activator.getResourceString("easyshell.page.table.header.column0.title")); //$NON-NLS-1$ + column1.setText(Activator.getResourceString("easyshell.page.table.header.title.column0")); //$NON-NLS-1$ column1.setResizable(false); TableColumn column2 = new TableColumn(table, SWT.LEFT); - column2.setText(Activator.getResourceString("easyshell.page.table.header.column1.title")); //$NON-NLS-1$ + column2.setText(Activator.getResourceString("easyshell.page.table.header.title.column1")); //$NON-NLS-1$ column2.setResizable(false); int availableRows = availableRows(pageComponent); @@ -120,8 +123,8 @@ protected Control createContents(Composite parent) { table.setLayoutData(gridData); tableViewer = new CheckboxTableViewer(table); - tableViewer.setLabelProvider(new CommandMenuDataLabelProvider()); - tableViewer.setContentProvider(new CommandMenuDataContentProvider()); + tableViewer.setLabelProvider(new MenuDataLabelProvider()); + tableViewer.setContentProvider(new MenuDataContentProvider()); // command store cmdStore = new CommandDataStore(Activator.getDefault().getPreferenceStore()); @@ -131,7 +134,7 @@ protected Control createContents(Composite parent) { cmdList = CommandDataDefaultCollection.getCommandsNative(cmdStore.getAllCommands()); // menu store - menuStore = new CommandMenuDataStore(Activator.getDefault().getPreferenceStore()); + menuStore = new MenuDataStore(Activator.getDefault().getPreferenceStore()); menuStore.load(); tableViewer.setInput(menuStore); tableViewer.setAllChecked(false); @@ -140,14 +143,14 @@ protected Control createContents(Composite parent) { tableViewer.addDoubleClickListener(new IDoubleClickListener() { @Override public void doubleClick(DoubleClickEvent event) { - edit(); + editDialog(); } }); tableViewer.addCheckStateListener(new ICheckStateListener() { @Override public void checkStateChanged(CheckStateChangedEvent event) { - CommandMenuData data = (CommandMenuData) event.getElement(); + MenuData data = (MenuData) event.getElement(); data.setEnabled(event.getChecked()); } }); @@ -157,6 +160,7 @@ public void checkStateChanged(CheckStateChangedEvent event) { public void selectionChanged(SelectionChangedEvent event) { IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection(); boolean selected = !selection.isEmpty(); + addCopyButton.setEnabled(selected); editButton.setEnabled(selected); removeButton.setEnabled(selected); upButton.setEnabled(selected); @@ -166,11 +170,11 @@ public void selectionChanged(SelectionChangedEvent event) { tableViewer.setSorter(new ViewerSorter() { public int compare(Viewer viewer, Object object1, Object object2) { - if (!(object1 instanceof CommandMenuData) || !(object2 instanceof CommandMenuData)) { + if (!(object1 instanceof MenuData) || !(object2 instanceof MenuData)) { return super.compare(viewer, object1, object2); } - CommandMenuData data1 = (CommandMenuData) object1; - CommandMenuData data2 = (CommandMenuData) object2; + MenuData data1 = (MenuData) object1; + MenuData data2 = (MenuData) object2; if (data1.getPosition() > data2.getPosition()) { return 1; } @@ -188,7 +192,7 @@ public boolean isSorterProperty(Object element, String property) { } }); - itemMover = new CommandMenuDataMover(table, menuStore); + itemMover = new MenuDataMover(table, menuStore); // button pageComponent Composite groupComponent = new Composite(pageComponent, SWT.NULL); @@ -203,77 +207,122 @@ public boolean isSorterProperty(Object element, String property) { groupComponent.setFont(font); // buttons - addButton = new Button(groupComponent, SWT.PUSH); - addButton.setText(Activator.getResourceString("easyshell.page.table.button.add")); //$NON-NLS-1$ - addButton.addSelectionListener(new SelectionAdapter() { + createNewButton(font, gridData, groupComponent); + + createCopyButton(font, gridData, groupComponent); + + createEditButton(font, gridData, groupComponent); + + createRemoveButton(font, gridData, groupComponent); + + createUpButton(font, gridData, groupComponent); + + createDownButton(font, gridData, groupComponent); + + configureTableResizing(table); + + Dialog.applyDialogFont(pageComponent); + // trigger the resize + table.getHorizontalBar().setVisible(true); + + // send event to refresh tableViewer + Event event = new Event(); + event.item = null; + tableViewer.refresh(); + tableViewer.getTable().notifyListeners(SWT.Selection, event); + //tableViewer.getControl().setEnabled(true); + + return pageComponent; + } + + private void createDownButton(Font font, GridData gridData, Composite groupComponent) { + downButton = new Button(groupComponent, SWT.PUSH); + downButton.setText(Activator.getResourceString("easyshell.page.table.button.text.down")); + downButton.setToolTipText(Activator.getResourceString("easyshell.page.table.button.tooltip.down")); + downButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { - add(); + down(); } }); - addButton.setLayoutData(gridData); - addButton.setFont(font); - setButtonLayoutData(addButton); + downButton.setLayoutData(gridData); + downButton.setFont(font); + setButtonLayoutData(downButton); + } - editButton = new Button(groupComponent, SWT.PUSH); - editButton.setText(Activator.getResourceString("easyshell.page.table.button.edit")); //$NON-NLS-1$ - editButton.addSelectionListener(new SelectionAdapter() { + private void createUpButton(Font font, GridData gridData, Composite groupComponent) { + upButton = new Button(groupComponent, SWT.PUSH); + upButton.setText(Activator.getResourceString("easyshell.page.table.button.text.up")); + upButton.setToolTipText(Activator.getResourceString("easyshell.page.table.button.tooltip.up")); + upButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { - edit(); + up(); } }); - editButton.setLayoutData(gridData); - editButton.setFont(font); - setButtonLayoutData(editButton); + upButton.setLayoutData(gridData); + upButton.setFont(font); + setButtonLayoutData(upButton); + } + private void createRemoveButton(Font font, GridData gridData, Composite groupComponent) { removeButton = new Button(groupComponent, SWT.PUSH); - removeButton.setText(Activator.getResourceString("easyshell.page.table.button.remove")); //$NON-NLS-1$ + removeButton.setText(Activator.getResourceString("easyshell.page.table.button.text.remove")); + removeButton.setToolTipText(Activator.getResourceString("easyshell.page.table.button.tooltip.remove")); removeButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { - remove(); + removeDialog(); } }); + removeButton.setLayoutData(gridData); removeButton.setFont(font); setButtonLayoutData(removeButton); + } - upButton = new Button(groupComponent, SWT.PUSH); - upButton.setText(Activator.getResourceString("easyshell.page.table.button.up")); //$NON-NLS-1$ - upButton.addSelectionListener(new SelectionAdapter() { + private void createEditButton(Font font, GridData gridData, Composite groupComponent) { + editButton = new Button(groupComponent, SWT.PUSH); + editButton.setText(Activator.getResourceString("easyshell.page.table.button.text.edit")); + editButton.setToolTipText(Activator.getResourceString("easyshell.page.table.button.tooltip.edit")); + editButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { - up(); + editDialog(); } }); - upButton.setFont(font); - setButtonLayoutData(upButton); + editButton.setLayoutData(gridData); + editButton.setFont(font); + setButtonLayoutData(editButton); + } - downButton = new Button(groupComponent, SWT.PUSH); - downButton.setText(Activator.getResourceString("easyshell.page.table.button.down")); //$NON-NLS-1$ - downButton.addSelectionListener(new SelectionAdapter() { + private void createCopyButton(Font font, GridData gridData, Composite groupComponent) { + addCopyButton = new Button(groupComponent, SWT.PUSH); + addCopyButton.setText(Activator.getResourceString("easyshell.page.table.button.text.copy")); + addCopyButton.setToolTipText(Activator.getResourceString("easyshell.page.table.button.tooltip.copy")); + addCopyButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { - down(); + addCopyDialog(); } }); - downButton.setFont(font); - setButtonLayoutData(downButton); - - configureTableResizing(table); - - Dialog.applyDialogFont(pageComponent); - // trigger the resize - table.getHorizontalBar().setVisible(true); - - // send event to refresh tableViewer - Event event = new Event(); - event.item = null; - tableViewer.refresh(); - tableViewer.getTable().notifyListeners(SWT.Selection, event); - //tableViewer.getControl().setEnabled(true); + addCopyButton.setLayoutData(gridData); + addCopyButton.setFont(font); + setButtonLayoutData(addCopyButton); + } - return pageComponent; + private void createNewButton(Font font, GridData gridData, Composite groupComponent) { + addNewButton = new Button(groupComponent, SWT.PUSH); + addNewButton.setText(Activator.getResourceString("easyshell.page.table.button.text.new")); + addNewButton.setToolTipText(Activator.getResourceString("easyshell.page.table.button.tooltip.new")); + addNewButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + addNewDialog(); + } + }); + addNewButton.setLayoutData(gridData); + addNewButton.setFont(font); + setButtonLayoutData(addNewButton); } private int availableRows(Composite parent) { @@ -367,41 +416,57 @@ public void controlResized(ControlEvent e) { } } - private void add() { - CommandMenuData data = new CommandMenuData(); - data.setCommandData(cmdList.get(0), false); - CommandMenuDataDialog dialog = new CommandMenuDataDialog(getShell(), data, cmdStore, cmdList, false); + private void addNewDialog() { + MenuData data = new MenuData(cmdList.get(0)); + MenuDataDialog dialog = new MenuDataDialog(getShell(), data, cmdStore, cmdList, false); if (dialog.open() == Window.OK) { menuStore.add(data); - tableViewer.refresh(); - tableViewer.setChecked(data, data.isEnabled()); - tableViewer.setSelection(new StructuredSelection(data)); + refreshTableViewer(data); return; } } - private void remove() { + private void addCopyDialog() { IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection(); - Iterator elements = selection.iterator(); - while (elements.hasNext()) { - CommandMenuData data = (CommandMenuData) elements.next(); - menuStore.delete(data); + MenuData data = new MenuData((MenuData)selection.getFirstElement()); + MenuDataDialog dialog = new MenuDataDialog(getShell(), data, cmdStore, cmdList, false); + if (dialog.open() == Window.OK) { + menuStore.add(data); + refreshTableViewer(data); + return; } - tableViewer.refresh(); } - private void edit() { + private void editDialog() { IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection(); - CommandMenuData data = (CommandMenuData) selection.getFirstElement(); - CommandMenuDataDialog dialog = new CommandMenuDataDialog(getShell(), data, cmdStore, cmdList, true); + MenuData data = (MenuData) selection.getFirstElement(); + MenuDataDialog dialog = new MenuDataDialog(getShell(), data, cmdStore, cmdList, true); if (dialog.open() == Window.OK) { - tableViewer.refresh(); - tableViewer.setChecked(data, data.isEnabled()); - tableViewer.setSelection(new StructuredSelection(data)); + refreshTableViewer(data); return; } } + private void removeDialog() { + String title = Activator.getResourceString("easyshell.page.table.dialog.remove.title"); + String question = Activator.getResourceString("easyshell.page.table.dialog.remove.question"); + MessageDialog dialog = new MessageDialog( + null, title, null, question, + MessageDialog.QUESTION, + new String[] {"Yes", "No"}, + 1); // no is the default + int result = dialog.open(); + if (result == 0) { + IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection(); + Iterator elements = selection.iterator(); + while (elements.hasNext()) { + MenuData data = (MenuData) elements.next(); + menuStore.delete(data); + } + tableViewer.refresh(); + } + } + private void up() { itemMover.moveCurrentSelectionUp(); tableViewer.refresh(); @@ -412,4 +477,10 @@ private void down() { tableViewer.refresh(); } + private void refreshTableViewer(MenuData data) { + tableViewer.refresh(); + tableViewer.setChecked(data, data.isEnabled()); + tableViewer.setSelection(new StructuredSelection(data)); + } + } \ No newline at end of file diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java similarity index 90% rename from plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuData.java rename to plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java index dbf8fca4..1b6b79b7 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java @@ -14,7 +14,7 @@ import java.util.StringTokenizer; import java.util.UUID; -public class CommandMenuData { +public class MenuData { // status private int position = 0; @@ -27,15 +27,20 @@ public class CommandMenuData { // command data private CommandData commandData; - public CommandMenuData(CommandData commandData) { + public MenuData(CommandData commandData) { this.commandData = commandData; setDefaultName(); } - public CommandMenuData() { + public MenuData(MenuData data) { + this(data.getCommandData()); + this.name = data.getName(); } - public int getPosition() { + public MenuData() { + } + + public int getPosition() { return position; } @@ -56,10 +61,10 @@ public CommandData getCommandData() { } public boolean equals(Object object) { - if(!(object instanceof CommandMenuData)) { + if(!(object instanceof MenuData)) { return false; } - CommandMenuData data = (CommandMenuData)object; + MenuData data = (MenuData)object; if( data.getPosition() == this.getPosition() && data.getName().equals(this.getName()) && data.getCommandData().equals(this.getCommandData()) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuDataContentProvider.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataContentProvider.java similarity index 80% rename from plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuDataContentProvider.java rename to plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataContentProvider.java index a105f1de..9fe95b26 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuDataContentProvider.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataContentProvider.java @@ -14,9 +14,9 @@ import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.Viewer; -public class CommandMenuDataContentProvider implements IStructuredContentProvider { +public class MenuDataContentProvider implements IStructuredContentProvider { - private CommandMenuDataStore store; + private MenuDataStore store; public Object[] getElements(Object inputElement) { return store.getCommandMenuDataArray(); @@ -27,8 +27,8 @@ public void dispose() { } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - if(newInput instanceof CommandMenuDataStore) { - store = (CommandMenuDataStore)newInput; + if(newInput instanceof MenuDataStore) { + store = (MenuDataStore)newInput; } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java similarity index 55% rename from plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuDataDialog.java rename to plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java index 2c70a11b..0ac767df 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java @@ -11,6 +11,7 @@ package de.anbos.eclipse.easyshell.plugin.preferences; +import java.text.MessageFormat; import java.util.List; import org.eclipse.jface.dialogs.MessageDialog; @@ -35,35 +36,35 @@ import de.anbos.eclipse.easyshell.plugin.Activator; -public class CommandMenuDataDialog extends StatusDialog { +public class MenuDataDialog extends StatusDialog { - private CommandMenuData data; + private MenuData data; private CommandDataStore cmdStore; private List cmdList; - private boolean edit; private Button enabledCheckBox; private Text nameText; private Text commandText; private CCombo commandCombo; - private Button addButton; + private Button addNewButton; + private Button addCopyButton; private Button editButton; + private Button removeButton; - public CommandMenuDataDialog(Shell parent, CommandMenuData data, CommandDataStore cmdStore, List cmdList, boolean edit) { + public MenuDataDialog(Shell parent, MenuData data, CommandDataStore cmdStore, List cmdList, boolean edit) { super(parent); this.data = data; this.cmdStore = cmdStore; this.cmdList = cmdList; - this.edit = edit; // do layout and title setShellStyle(getShellStyle() | SWT.MAX); // set title String title = null; if(edit) { - title = Activator.getResourceString("easyshell.menu.editor.dialog.edit.title"); //$NON-NLS-1$ + title = Activator.getResourceString("easyshell.menu.editor.dialog.title.edit"); //$NON-NLS-1$ } else { - title = Activator.getResourceString("easyshell.menu.editor.dialog.new.title"); //$NON-NLS-1$ + title = Activator.getResourceString("easyshell.menu.editor.dialog.title.new"); //$NON-NLS-1$ } setTitle(title); } @@ -88,9 +89,9 @@ public Control createDialogArea(Composite parent) { pageComponent.setFont(font); // define group1 Group pageGroup1 = new Group(pageComponent, SWT.SHADOW_ETCHED_IN); - pageGroup1.setText(Activator.getResourceString("easyshell.menu.editor.dialog.title")); + pageGroup1.setText(Activator.getResourceString("easyshell.menu.editor.dialog.title.group1")); GridLayout layout1 = new GridLayout(); - layout1.numColumns = 2; + layout1.numColumns = 3; layout1.makeColumnsEqualWidth = false; layout1.marginWidth = 5; layout1.marginHeight = 4; @@ -99,46 +100,80 @@ public Control createDialogArea(Composite parent) { pageGroup1.setLayoutData(gridData1); pageGroup1.setFont(font); // create activity checkbox - createEnabledCheckBox(pageGroup1); + createEnabledCheckBox(pageGroup1);createNewButton(font, pageGroup1, gridData1); // create selected command combo - createCommandCombo(pageGroup1); - //create input nameText field - commandText = createTextField(pageGroup1, Activator.getResourceString("easyshell.menu.editor.dialog.command.label"), data.getCommandData().getCommand(), false); + createCommandCombo(pageGroup1);createCopyButton(font, pageGroup1, gridData1); + //create input commandText field + commandText = createTextField(pageGroup1, Activator.getResourceString("easyshell.menu.editor.dialog.label.command"), data.getCommandData().getCommand(), false); // buttons - addButton = new Button(pageGroup1, SWT.PUSH); - addButton.setText(Activator.getResourceString("easyshell.page.table.button.add")); //$NON-NLS-1$ - addButton.addSelectionListener(new SelectionAdapter() { + createEditButton(font, pageGroup1, gridData1); + //create input nameText field + nameText = createTextField(pageGroup1, Activator.getResourceString("easyshell.menu.editor.dialog.label.name"), data.getName(), true); + createRemoveButton(font, pageGroup1, gridData1); + + refreshCommandCombo(); + + return pageComponent; + } + + private void createRemoveButton(Font font, Group pageGroup1, GridData gridData1) { + removeButton = new Button(pageGroup1, SWT.PUSH); + removeButton.setText(Activator.getResourceString("easyshell.menu.editor.dialog.button.text.remove")); + removeButton.setToolTipText(Activator.getResourceString("easyshell.menu.editor.dialog.button.tooltip.remove")); + removeButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { - add(); + removeDialog(); } }); - addButton.setLayoutData(gridData1); - addButton.setFont(font); - setButtonLayoutData(addButton); + removeButton.setLayoutData(gridData1); + removeButton.setFont(font); + setButtonLayoutData(removeButton); + } + + private void createEditButton(Font font, Group pageGroup1, GridData gridData1) { editButton = new Button(pageGroup1, SWT.PUSH); - editButton.setText(Activator.getResourceString("easyshell.page.table.button.edit")); //$NON-NLS-1$ + editButton.setText(Activator.getResourceString("easyshell.menu.editor.dialog.button.text.edit")); + editButton.setToolTipText(Activator.getResourceString("easyshell.menu.editor.dialog.button.tooltip.edit")); editButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { - edit(); + editDialog(); } }); editButton.setLayoutData(gridData1); editButton.setFont(font); setButtonLayoutData(editButton); + } - //create input nameText field - nameText = createTextField(pageGroup1, Activator.getResourceString("easyshell.menu.editor.dialog.name.label"), data.getName(), true); - - //if (edit) { - // send event to refresh - Event event = new Event(); - event.item = null; - commandCombo.notifyListeners(SWT.Selection, event); - //} + private void createCopyButton(Font font, Group pageGroup1, GridData gridData1) { + addCopyButton = new Button(pageGroup1, SWT.PUSH); + addCopyButton.setText(Activator.getResourceString("easyshell.menu.editor.dialog.button.text.copy")); + addCopyButton.setToolTipText(Activator.getResourceString("easyshell.menu.editor.dialog.button.tooltip.copy")); + addCopyButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + addCopyDialog(); + } + }); + addCopyButton.setLayoutData(gridData1); + addCopyButton.setFont(font); + setButtonLayoutData(addCopyButton); + } - return pageComponent; + private void createNewButton(Font font, Group pageGroup1, GridData gridData1) { + addNewButton = new Button(pageGroup1, SWT.PUSH); + addNewButton.setText(Activator.getResourceString("easyshell.menu.editor.dialog.button.text.new")); + addNewButton.setToolTipText(Activator.getResourceString("easyshell.menu.editor.dialog.button.tooltip.new")); + addNewButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + addNewDialog(); + } + }); + addNewButton.setLayoutData(gridData1); + addNewButton.setFont(font); + setButtonLayoutData(addNewButton); } protected void okPressed() { @@ -151,48 +186,85 @@ protected void okPressed() { super.okPressed(); } - private void add() { - CommandData data = new CommandData(); + private void addDialog(CommandData data) { CommandDataDialog dialog = new CommandDataDialog(getShell(), data, false); if (dialog.open() == Window.OK) { - cmdStore.add(data); - cmdStore.save(); - cmdList.add(data); - String[] names = getAllCommandsAsComboNames(cmdList); - commandCombo.setItems(names); - commandCombo.select(names.length-1); - // send event to refresh - Event event = new Event(); - event.item = null; - commandCombo.notifyListeners(SWT.Selection, event); - /* - tableViewer.refresh(); - tableViewer.setChecked(data, data.isEnabled()); - tableViewer.setSelection(new StructuredSelection(data)); - */ - return; + addCommand(data); + refreshCommandCombo(); } } - private void edit() { + private void addCommand(CommandData data) { + cmdStore.add(data); + cmdStore.save(); + cmdList.add(data); + String[] names = getAllCommandsAsComboNames(cmdList); + commandCombo.setItems(names); + commandCombo.select(names.length-1); + } + + private void removeCommand(int index, CommandData data) { + cmdStore.delete(data); + cmdStore.save(); + //cmdList.remove(data); // no need to search for data, use index instead: + cmdList.remove(index); + String[] names = getAllCommandsAsComboNames(cmdList); + commandCombo.setItems(names); + commandCombo.select(names.length-1); + } + + private void addNewDialog() { + CommandData data = new CommandData(PresetType.presetUser, Utils.getOS(), "MyNewCommand", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOther, "my_new_command"); + addDialog(data); + } + + private void addCopyDialog() { + int index = commandCombo.getSelectionIndex(); + CommandData data = new CommandData(cmdList.get(index)); + data.setPresetType(PresetType.presetUser); + addDialog(data); + } + + private void editDialog() { int index = commandCombo.getSelectionIndex(); CommandData data = cmdList.get(index); CommandDataDialog dialog = new CommandDataDialog(getShell(), data, true); if (dialog.open() == Window.OK) { - commandCombo.setItem(index, getCommandAsComboName(data)); - // send event to refresh - Event event = new Event(); - event.item = null; - commandCombo.notifyListeners(SWT.Selection, event); - /* - tableViewer.refresh(); - tableViewer.setChecked(data, data.isEnabled()); - tableViewer.setSelection(new StructuredSelection(data)); - */ - return; + replaceCommand(index, data); + refreshCommandCombo(); } } + private void removeDialog() { + int index = commandCombo.getSelectionIndex(); + String title = Activator.getResourceString("easyshell.menu.editor.dialog.title.remove"); + String question = MessageFormat.format( + Activator.getResourceString("easyshell.menu.editor.dialog.question.remove"), + commandCombo.getItem(index)); + MessageDialog dialog = new MessageDialog( + null, title, null, question, + MessageDialog.QUESTION, + new String[] {"Yes", "No"}, + 1); // no is the default + int result = dialog.open(); + if (result == 0) { + CommandData data = cmdList.get(index); + removeCommand(index, data); + refreshCommandCombo(); + } + } + + private void replaceCommand(int index, CommandData data) { + commandCombo.setItem(index, getCommandAsComboName(data)); + } + + private void refreshCommandCombo() { + // send event to refresh + Event event = new Event(); + event.item = null; + commandCombo.notifyListeners(SWT.Selection, event); + } + private boolean validateValues() { final String title = Activator.getResourceString("easyshell.menu.editor.dialog.error.incompletedata.title"); @@ -206,7 +278,7 @@ private boolean validateValues() { boolean valid = true; // check name - String text = Activator.getResourceString("easyshell.menu.editor.dialog.error.name.text"); + String text = Activator.getResourceString("easyshell.menu.editor.dialog.error.text.name"); if ( (nameText.getText() == null) || (nameText.getText().length() <= 0)) { valid = false; } @@ -222,18 +294,14 @@ private void createEnabledCheckBox(Composite parent) { // draw label Label comboLabel = new Label(parent,SWT.LEFT); comboLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END)); - comboLabel.setText(Activator.getResourceString("easyshell.menu.editor.dialog.active.label")); //$NON-NLS-1$ + comboLabel.setText(Activator.getResourceString("easyshell.menu.editor.dialog.label.active")); //$NON-NLS-1$ // draw checkbox enabledCheckBox = new Button(parent,SWT.CHECK); - if(edit) { - enabledCheckBox.setSelection(this.data.isEnabled()); - } else { - enabledCheckBox.setSelection(true); - } + enabledCheckBox.setSelection(this.data.isEnabled()); } private String getCommandAsComboName(CommandData data) { - return data.getOS().getName() + " - " + data.getCommandType().getName() + " - " + data.getName(); + return data.getPresetType().getName() + " - " + data.getOS().getName() + " - " + data.getCommandType().getName() + " - " + data.getName(); } private String[] getAllCommandsAsComboNames(List list) { @@ -248,7 +316,7 @@ private void createCommandCombo(Composite parent) { // draw label Label comboLabel = new Label(parent,SWT.LEFT); comboLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END)); - comboLabel.setText(Activator.getResourceString("easyshell.menu.editor.dialog.combo.label")); //$NON-NLS-1$ + comboLabel.setText(Activator.getResourceString("easyshell.menu.editor.dialog.label.combo")); //$NON-NLS-1$ // draw combo commandCombo = new CCombo(parent,SWT.BORDER); commandCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); @@ -263,21 +331,20 @@ public void widgetSelected(SelectionEvent e) { data.setCommandData(cmdList.get(index), true); nameText.setText(data.getName()); commandText.setText(data.getCommandData().getCommand()); + boolean isUserDefined = data.getCommandData().getPresetType() == PresetType.presetUser; + editButton.setEnabled(isUserDefined); + removeButton.setEnabled(isUserDefined); } @Override public void widgetDefaultSelected(SelectionEvent e) { // TODO Auto-generated method stub } }); - if (edit) { - for(int i = 0 ; i < cmdList.size() ; i++) { - if (cmdList.get(i).equals(this.data.getCommandData())) { - commandCombo.select(i); - return; - } + for(int i = 0 ; i < cmdList.size() ; i++) { + if (cmdList.get(i).equals(this.data.getCommandData())) { + commandCombo.select(i); + return; } - } else { - commandCombo.select(0); } } @@ -289,10 +356,8 @@ private Text createTextField(Composite parent, String labelText, String editValu // draw textfield Text text = new Text(parent,SWT.BORDER); text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - if(edit) { - text.setText(editValue); - text.setEditable(editable); - } + text.setText(editValue); + text.setEditable(editable); return text; } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuDataLabelProvider.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataLabelProvider.java similarity index 82% rename from plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuDataLabelProvider.java rename to plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataLabelProvider.java index 61d8ea1f..1393e26c 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuDataLabelProvider.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataLabelProvider.java @@ -17,13 +17,13 @@ import de.anbos.eclipse.easyshell.plugin.Activator; -public class CommandMenuDataLabelProvider extends LabelProvider implements ITableLabelProvider { +public class MenuDataLabelProvider extends LabelProvider implements ITableLabelProvider { public Image getColumnImage(Object element, int columnIndex) { - if(!(element instanceof CommandMenuData)) { + if(!(element instanceof MenuData)) { return null; } - CommandMenuData data = (CommandMenuData)element; + MenuData data = (MenuData)element; switch(columnIndex) { case 0: return new Image(null, Activator.getImageDescriptor(data.getCommandData().getTypeIcon()).getImageData()); @@ -33,10 +33,10 @@ public Image getColumnImage(Object element, int columnIndex) { } public String getColumnText(Object element, int columnIndex) { - if(!(element instanceof CommandMenuData)) { + if(!(element instanceof MenuData)) { return ""; //$NON-NLS-1$ } - CommandMenuData data = (CommandMenuData)element; + MenuData data = (MenuData)element; switch(columnIndex) { case 0: return data.getName(); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuDataMover.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataMover.java similarity index 78% rename from plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuDataMover.java rename to plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataMover.java index bb36e35d..8db38381 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuDataMover.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataMover.java @@ -16,14 +16,14 @@ import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableItem; -public class CommandMenuDataMover implements SelectionListener { +public class MenuDataMover implements SelectionListener { private Table table; - private CommandMenuDataStore store; + private MenuDataStore store; - private CommandMenuData currentSelection; + private MenuData currentSelection; - public CommandMenuDataMover(Table table, CommandMenuDataStore store) { + public MenuDataMover(Table table, MenuDataStore store) { this.table = table; this.store = store; table.addSelectionListener(this); @@ -33,7 +33,7 @@ public void moveCurrentSelectionUp() { if(currentSelection == null) { return; } - CommandMenuData previousElement = store.getPreviousElement(currentSelection); + MenuData previousElement = store.getPreviousElement(currentSelection); if(previousElement == null) { return; } @@ -47,7 +47,7 @@ public void moveCurrentSelectionDown() { if(currentSelection == null) { return; } - CommandMenuData nextElement = store.getNextElement(currentSelection); + MenuData nextElement = store.getNextElement(currentSelection); if(nextElement == null) { return; } @@ -68,10 +68,10 @@ public void widgetSelected(SelectionEvent e) { currentSelection = null; return; } - if(item == null || !(item.getData() instanceof CommandMenuData)) { + if(item == null || !(item.getData() instanceof MenuData)) { currentSelection = null; return; } - currentSelection = (CommandMenuData)item.getData(); + currentSelection = (MenuData)item.getData(); } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuDataStore.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java similarity index 60% rename from plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuDataStore.java rename to plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java index 07a34f49..afd1d6f5 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandMenuDataStore.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java @@ -19,38 +19,38 @@ import org.eclipse.jface.preference.IPreferenceStore; -public class CommandMenuDataStore { +public class MenuDataStore { private IPreferenceStore store; - private List items; + private List items; private DataObjectComparator comparator; - public CommandMenuDataStore(IPreferenceStore store) { - items = new ArrayList(); + public MenuDataStore(IPreferenceStore store) { + items = new ArrayList(); this.store = store; } - public List getCommandMenuDataList() { + public List getCommandMenuDataList() { return items; } - public CommandMenuData[] getCommandMenuDataArray() { - List allItems = getCommandMenuDataList(); + public MenuData[] getCommandMenuDataArray() { + List allItems = getCommandMenuDataList(); if(allItems.size() <= 0) { - return new CommandMenuData[0]; + return new MenuData[0]; } - CommandMenuData[] allArray = new CommandMenuData[allItems.size()]; + MenuData[] allArray = new MenuData[allItems.size()]; for(int i = 0 ; i < allArray.length ; i++) { - allArray[i] = (CommandMenuData)allItems.get(i); + allArray[i] = (MenuData)allItems.get(i); } return allArray; } - public List getEnabledCommandMenuDataList() { - List checkedItems = new ArrayList(); - Iterator dataIterator = items.iterator(); + public List getEnabledCommandMenuDataList() { + List checkedItems = new ArrayList(); + Iterator dataIterator = items.iterator(); while(dataIterator.hasNext()) { - CommandMenuData data = (CommandMenuData)dataIterator.next(); + MenuData data = (MenuData)dataIterator.next(); if(data.isEnabled()) { checkedItems.add(data); } @@ -58,25 +58,25 @@ public List getEnabledCommandMenuDataList() { return checkedItems; } - public CommandMenuData[] getEnabledCommandMenuDataArray() { - List checkedItems = getEnabledCommandMenuDataList(); + public MenuData[] getEnabledCommandMenuDataArray() { + List checkedItems = getEnabledCommandMenuDataList(); if(checkedItems.size() <= 0) { - return new CommandMenuData[0]; + return new MenuData[0]; } - CommandMenuData[] checked = new CommandMenuData[checkedItems.size()]; + MenuData[] checked = new MenuData[checkedItems.size()]; for(int i = 0 ; i < checked.length ; i++) { - checked[i] = (CommandMenuData)checkedItems.get(i); + checked[i] = (MenuData)checkedItems.get(i); } return checked; } - public CommandMenuData getPreviousElement(CommandMenuData data) { + public MenuData getPreviousElement(MenuData data) { sort(); for(int i = 0 ; i < items.size() ; i++) { - CommandMenuData item = (CommandMenuData)items.get(i); + MenuData item = (MenuData)items.get(i); if(item.equals(data)) { try { - return (CommandMenuData)items.get(i - 1); + return (MenuData)items.get(i - 1); } catch(Throwable t) { return null; } @@ -85,13 +85,13 @@ public CommandMenuData getPreviousElement(CommandMenuData data) { return null; } - public CommandMenuData getNextElement(CommandMenuData data) { + public MenuData getNextElement(MenuData data) { sort(); for(int i = 0 ; i < items.size() ; i++) { - CommandMenuData item = (CommandMenuData)items.get(i); + MenuData item = (MenuData)items.get(i); if(item.equals(data)) { try { - return (CommandMenuData)items.get(i + 1); + return (MenuData)items.get(i + 1); } catch(Throwable t) { return null; } @@ -100,18 +100,18 @@ public CommandMenuData getNextElement(CommandMenuData data) { return null; } - public CommandMenuData getLastElement() { + public MenuData getLastElement() { sort(); int index = items.size() - 1; if(index < 0) { return null; } - return (CommandMenuData)items.get(index); + return (MenuData)items.get(index); } - public void add(CommandMenuData data) { + public void add(MenuData data) { int position = 0; - CommandMenuData lastElement = getLastElement(); + MenuData lastElement = getLastElement(); if(lastElement != null) { position = lastElement.getPosition() + 1; } @@ -120,7 +120,7 @@ public void add(CommandMenuData data) { sort(); } - public void delete(CommandMenuData data) { + public void delete(MenuData data) { items.remove(data); sort(); } @@ -135,7 +135,7 @@ public void loadDefaults() { } public void load() { - CommandMenuData[] items = PreferenceValueConverter.asCommandMenuDataArray(store.getString(Constants.PREF_MENU)); + MenuData[] items = PreferenceValueConverter.asCommandMenuDataArray(store.getString(Constants.PREF_MENU)); this.items.clear(); for(int i = 0 ; i < items.length ; i++) { this.items.add(items[i]); @@ -153,19 +153,19 @@ private void sort() { } Collections.sort(items,comparator); for (int i=0;i { public int compare(Object object1, Object object2) { - CommandMenuData data1 = null; - CommandMenuData data2 = null; - if(object1 instanceof CommandMenuData) { - data1 = (CommandMenuData)object1; + MenuData data1 = null; + MenuData data2 = null; + if(object1 instanceof MenuData) { + data1 = (MenuData)object1; } - if(object2 instanceof CommandMenuData) { - data2 = (CommandMenuData)object2; + if(object2 instanceof MenuData) { + data2 = (MenuData)object2; } if(data1 == null || data2 == null) { return -1; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceValueConverter.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceValueConverter.java index 8bb445be..5cf6f786 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceValueConverter.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceValueConverter.java @@ -32,9 +32,9 @@ public static String asCommandDataString(List items) { return buffer.toString(); } - public static String asCommandMenuDataString(List items) { + public static String asCommandMenuDataString(List items) { StringBuffer buffer = new StringBuffer(); - for(CommandMenuData item : items) { + for(MenuData item : items) { buffer.append(asCommandMenuDataString(item)); buffer.append(ITEM_DELIMITER); } @@ -45,7 +45,7 @@ public static final String asCommandDataString(CommandData data) { return data.serialize(VALUE_DELIMITER); } - public static final String asCommandMenuDataString(CommandMenuData data) { + public static final String asCommandMenuDataString(MenuData data) { return data.serialize(VALUE_DELIMITER); } @@ -58,9 +58,9 @@ public static CommandData[] asCommandDataArray(String value) { return items; } - public static CommandMenuData[] asCommandMenuDataArray(String value) { + public static MenuData[] asCommandMenuDataArray(String value) { StringTokenizer tokenizer = new StringTokenizer(value,ITEM_DELIMITER); - CommandMenuData[] items = new CommandMenuData[tokenizer.countTokens()]; + MenuData[] items = new MenuData[tokenizer.countTokens()]; for(int i = 0 ; i < items.length ; i++) { items[i] = asCommandMenuData(tokenizer.nextToken()); } @@ -73,8 +73,8 @@ public static CommandData asCommandData(String value) { return data; } - public static CommandMenuData asCommandMenuData(String value) { - CommandMenuData data = new CommandMenuData(); + public static MenuData asCommandMenuData(String value) { + MenuData data = new MenuData(); data.deserialize(value, null, VALUE_DELIMITER); return data; } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetType.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetType.java new file mode 100644 index 00000000..e49c1619 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetType.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +import java.util.ArrayList; +import java.util.List; + +public enum PresetType { + presetUnknown(-1, "Unknown"), + presetPlugin(0, "Plugin"), + presetUser(1, "User"); + // attributes + private final int id; + private final String name; + // construct + PresetType(int id, String name) { + this.id = id; + this.name = name; + } + public int getId() { + return id; + } + public String getName() { + return name; + } + public static PresetType getFromId(int id) { + PresetType ret = presetUnknown; + for(int i = 0; i < PresetType.values().length; i++) { + if (PresetType.values()[i].getId() == id) { + ret = PresetType.values()[i]; + break; + } + } + return ret; + } + public static PresetType getFromName(String name) { + PresetType ret = presetUnknown; + for(int i = 0; i < PresetType.values().length; i++) { + if (PresetType.values()[i].getName().equals(name)) { + ret = PresetType.values()[i]; + break; + } + } + return ret; + } + public static PresetType getFromEnum(String name) { + PresetType ret = presetUnknown; + for(int i = 0; i < PresetType.values().length; i++) { + if (PresetType.values()[i].toString().equals(name)) { + ret = PresetType.values()[i]; + break; + } + } + return ret; + } + public static List getNamesAsList() { + List list = new ArrayList(); + for(int i = 0; i < PresetType.values().length; i++) { + list.add(PresetType.values()[i].getName()); + } + return list; + } +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Utils.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Utils.java new file mode 100644 index 00000000..6f42b369 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Utils.java @@ -0,0 +1,207 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.dnd.TextTransfer; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.ToolTip; + +public class Utils { + + public static OS getOS() { + OS os = OS.osUnknown; + /* possible OS string: + AIX + Digital UNIX + FreeBSD + HP UX + Irix + Linux + Mac OS + Mac OS X + MPE/iX + Netware 4.11 + OS/2 + Solaris + Windows 95 + Windows 98 + Windows NT + Windows Me + Windows 2000 + Windows XP + Windows 2003 + Windows CE + Windows Vista + Windows 7 + */ + String osname = System.getProperty("os.name", "").toLowerCase(); + if (osname.indexOf("windows") != -1) { + os = OS.osWindows; + } else if (osname.indexOf("mac os x") != -1) { + os = OS.osMacOSX; + } else if ( + osname.indexOf("unix") != -1 + || osname.indexOf("irix") != -1 + || osname.indexOf("freebsd") != -1 + || osname.indexOf("hp-ux") != -1 + || osname.indexOf("aix") != -1 + || osname.indexOf("sunos") != -1 + || osname.indexOf("linux") != -1 + ) + { + os = OS.osLinux; + } + return os; + } + + public static LinuxDesktop detectLinuxDesktop() { + LinuxDesktop resultCode = Utils.detectDesktopSession(); + /* + if (resultCode == LinuxDesktop.desktopUnknown) + { + if (isCde()) + resultCode = LinuxDesktop.desktopCde; + } + */ + return resultCode; + } + + /** + * detects desktop from $DESKTOP_SESSION + */ + public static LinuxDesktop detectDesktopSession() { + ArrayList command = new ArrayList(); + command.add("sh"); + command.add("-c"); + command.add("echo \"$DESKTOP_SESSION\""); + // fill the map + Map desktops = new HashMap(); + desktops.put("kde", LinuxDesktop.desktopKde); + desktops.put("gnome", LinuxDesktop.desktopGnome); + desktops.put("cinnamon", LinuxDesktop.desktopCinnamon); + desktops.put("xfce", LinuxDesktop.desktopXfce); + // execute + String desktop = Utils.isExpectedCommandOutput(command, desktops, true); + if (desktop != null && !desktop.isEmpty()) { + return (LinuxDesktop)desktops.get(desktop); + } + return LinuxDesktop.desktopUnknown; + } + + /** + * detects programs from $DESKTOP_SESSION + */ + public static String detectLinuxDefaultFileBrowser() { + ArrayList command = new ArrayList(); + command.add("xdg-mime"); + command.add("query"); + command.add("default"); + command.add("inode/directory"); + // fill the map + Map fileBrowsers = new HashMap(); + fileBrowsers.put("nemo.desktop", "nemo"); + // execute + String fileBrowser = Utils.isExpectedCommandOutput(command, fileBrowsers, true); + if (fileBrowser != null && !fileBrowser.isEmpty()) { + return (String)fileBrowsers.get(fileBrowser); + } + return null; + } + + /** + * Detects which desktop is used on a unix / linux system. + * + * @todo use regex + * + * @return The type of desktop. + * @see detectDesktop + */ + private static String isExpectedCommandOutput(ArrayList command, Map expectedOutput, boolean toLowerCase) { + boolean found = false; + String expectedLine = null; + try { + Process proc = Runtime.getRuntime().exec(command.toArray(new String[1])); + BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream())); + String line = null; + while((line = in.readLine()) != null && !found) { + for(String key: expectedOutput.keySet()) { + // in case of * just something should be returned + if (key.indexOf("*") != -1) + { + if (line.isEmpty()) { + found = false; + break; + } else { + found = true; + } + } else { + if (toLowerCase) + line = line.toLowerCase(); + if(line.indexOf(key) != -1) { + found = true; + } + } + if (found) { + expectedLine = line; + break; + } + } + } + line = null; + BufferedReader err = new BufferedReader(new InputStreamReader(proc.getErrorStream())); + // If there is any error output, print it to + // stdout for debugging purposes + while((line = err.readLine()) != null) { + //Activator.getDefault().sysout(true, "detectDesktop stderr >" + line + "<"); + } + + int result = proc.waitFor(); + if(result != 0) { + // If there is any error code, print it to + // stdout for debugging purposes + //Activator.getDefault().sysout(true, "detectDesktop return code: " + result); + } + } catch(Exception e) { + e.printStackTrace(); + } + return expectedLine; + } + + public static void copyToClipboard(String cmdAll) { + Clipboard clipboard = new Clipboard(Display.getCurrent()); + TextTransfer textTransfer = TextTransfer.getInstance(); + Transfer[] transfers = new Transfer[]{textTransfer}; + Object[] data = new Object[]{cmdAll}; + clipboard.setContents(data, transfers); + clipboard.dispose(); + } + + public static void showToolTip(Control control, String title, String message) { + ToolTip tooltip = new ToolTip(control.getShell(), /*SWT.BALLOON | */SWT.ICON_INFORMATION); + tooltip.setAutoHide(true); + tooltip.setLocation(control.toDisplay(control.getSize().x/2, control.getSize().y + 5)); + tooltip.setText(title); + tooltip.setMessage(message); + tooltip.setVisible(true); + } + +} From 850e39159cf5014065ccc9dab3fb6dc267dad07a Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Tue, 12 Jul 2016 23:34:49 +0200 Subject: [PATCH 06/73] added resource type handling - use Combo instead of CCombo Signed-off-by: Andre Bossert --- .../easyshell/plugin/UIMessages.properties | 6 +- .../plugin/preferences/CommandData.java | 16 +-- .../CommandDataDefaultCollection.java | 62 +++++------ .../plugin/preferences/CommandDataDialog.java | 100 ++++++++++++------ .../plugin/preferences/CommandType.java | 8 ++ .../plugin/preferences/MenuDataDialog.java | 10 +- .../plugin/preferences/ResourceType.java | 83 +++++++++++++++ .../plugin/preferences/RessourceType.java | 75 ------------- 8 files changed, 208 insertions(+), 152 deletions(-) create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/ResourceType.java delete mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/RessourceType.java diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties index c9c862db..4c621923 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties @@ -48,9 +48,11 @@ easyshell.command.editor.dialog.tooltip.group1=Add your command here easyshell.command.editor.dialog.title.group2=Usable variables easyshell.command.editor.dialog.tooltip.group2=Double click at variables to copy them to clipboard easyshell.command.editor.dialog.error.title.incompletedata=Missing or wrong command detected -easyshell.command.editor.dialog.error.text.type=Please choose a valid type +easyshell.command.editor.dialog.error.text.resource=Please choose a valid resource type +easyshell.command.editor.dialog.error.text.type=Please choose a valid command type easyshell.command.editor.dialog.error.text.name=Please enter a valid name easyshell.command.editor.dialog.error.text.value=Please enter a valid command -easyshell.command.editor.dialog.label.combo=type: +easyshell.command.editor.dialog.label.combo1=type: +easyshell.command.editor.dialog.label.combo2=resource: easyshell.command.editor.dialog.label.name=name: easyshell.command.editor.dialog.label.value=command: diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java index 6b8ec016..cc4493e7 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java @@ -23,11 +23,11 @@ public class CommandData { private PresetType presetType = PresetType.presetUser; private OS os = OS.osUnknown; private String name = "MyNewCommand"; - private RessourceType resType = RessourceType.ressourceFileOrFolder; + private ResourceType resType = ResourceType.resourceFileOrFolder; private CommandType cmdType = CommandType.commandTypeOther; private String command = "my_new_command"; - public CommandData(PresetType presetType, OS os, String name, RessourceType resType, CommandType cmdType, String command) { + public CommandData(PresetType presetType, OS os, String name, ResourceType resType, CommandType cmdType, String command) { this.presetType = presetType; this.os = os; this.name = name; @@ -40,7 +40,7 @@ public CommandData(CommandData commandData) { this.presetType = commandData.getPresetType(); this.os = commandData.getOS(); this.name = commandData.getName(); - this.resType = commandData.getRessourceType(); + this.resType = commandData.getResourceType(); this.cmdType = commandData.getCommandType(); this.command = commandData.getCommand(); } @@ -68,7 +68,7 @@ public PresetType getPresetType() { return presetType; } - public RessourceType getRessourceType() { + public ResourceType getResourceType() { return resType; } @@ -100,7 +100,7 @@ public void setPresetType(PresetType presetType) { this.presetType = presetType; } - public void setRessourceType(RessourceType resType) { + public void setResourceType(ResourceType resType) { this.resType = resType; } @@ -121,7 +121,7 @@ public boolean equals(Object object) { data.getName().equals(this.getName()) && data.getOS() == this.getOS() && data.getPresetType() == this.getPresetType() && - data.getRessourceType() == this.getRessourceType() && + data.getResourceType() == this.getResourceType() && data.getCommandType() == this.getCommandType() && data.getCommand().equals(this.getCommand() ) @@ -145,14 +145,14 @@ public boolean deserialize(String value, StringTokenizer tokenizer, String delim setPresetType(PresetType.getFromEnum(tokenizer.nextToken())); setOs(OS.getFromEnum(tokenizer.nextToken())); setName(tokenizer.nextToken()); - setRessourceType(RessourceType.getFromEnum(tokenizer.nextToken())); + setResourceType(ResourceType.getFromEnum(tokenizer.nextToken())); setCommandType(CommandType.getFromEnum(tokenizer.nextToken())); setCommand(tokenizer.nextToken()); return true; } public String serialize(String delimiter) { - return Integer.toString(getPosition()) + delimiter + getId() + delimiter + getPresetType().toString() + delimiter + getOS().toString() + delimiter + getName() + delimiter + getRessourceType().toString() + delimiter + getCommandType().toString() + delimiter + getCommand() + delimiter; + return Integer.toString(getPosition()) + delimiter + getId() + delimiter + getPresetType().toString() + delimiter + getOS().toString() + delimiter + getName() + delimiter + getResourceType().toString() + delimiter + getCommandType().toString() + delimiter + getCommand() + delimiter; } public String getTypeIcon() { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java index 78bc7a25..b7b249b5 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java @@ -38,87 +38,87 @@ public static List getDefaultCommandsMenuStatic() { CommandDataDefaultCollection() { // Windows DOS-Shell - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "DOS-Shell", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "DOS-Shell", ResourceType.resourceFileOrFolder, CommandType.commandTypeOpen, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} cmd.exe /K")); - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "DOS-Shell", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "DOS-Shell", ResourceType.resourceFileOrFolder, CommandType.commandTypeRun, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} ${easyshell:resource_name}")); // Windows Explorer - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Explorer", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Explorer", ResourceType.resourceFileOrFolder, CommandType.commandTypeExplore, "explorer.exe /select, ${easyshell:resource_loc}")); // Windows PowerShell - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "PowerShell", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "PowerShell", ResourceType.resourceFileOrFolder, CommandType.commandTypeOpen, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} powershell.exe")); - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "PowerShell", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "PowerShell", ResourceType.resourceFileOrFolder, CommandType.commandTypeRun, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} powershell.exe -command ./''${easyshell:resource_name}''")); // Windows Cygwin (Bash) - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceFileOrFolder, CommandType.commandTypeOpen, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Cygwin\\bin\\bash.exe\"")); - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceFileOrFolder, CommandType.commandTypeRun, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Cygwin\\bin\\bash.exe\" -c ./''${easyshell:resource_name}''")); // Windows Console - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Console", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Console", ResourceType.resourceFileOrFolder, CommandType.commandTypeOpen, "console.exe -w \"${easyshell:project_name}\" -d ${easyshell:container_loc}")); - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceFileOrFolder, CommandType.commandTypeRun, "console.exe -w \"${easyshell:project_name}\" -d ${easyshell:container_loc} -r \"/k\\\"${easyshell:resource_name}\\\"\"")); // Windows Git-Bash - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Git-Bash", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Git-Bash", ResourceType.resourceFileOrFolder, CommandType.commandTypeOpen, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Program Files (x86)\\Git\\bin\\bash.exe\" --login -i")); - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceFileOrFolder, CommandType.commandTypeRun, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Program Files (x86)\\Git\\bin\\bash.exe\" --login -i -c ./''${easyshell:resource_name}''")); // Windows ConEmu - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "ConEmu", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "ConEmu", ResourceType.resourceFileOrFolder, CommandType.commandTypeOpen, "ConEmu.exe /Title \"${easyshell:project_name}\" /Dir \"${easyshell:container_loc}\" /Single /cmd cmd")); - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceFileOrFolder, CommandType.commandTypeRun, "ConEmu.exe /Title \"${easyshell:project_name}\" /Dir \"${easyshell:container_loc}\" /Single /cmd \"${easyshell:resource_name}\"")); // Windows TotalCommander - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "TotalCommander", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "TotalCommander", ResourceType.resourceFileOrFolder, CommandType.commandTypeExplore, "totalcmd.exe /O /T ${easyshell:container_loc}")); // Windows Clipboard - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Full path", RessourceType.ressourceFileOrFolder, CommandType.commandTypeClipboard, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Full path", ResourceType.resourceFileOrFolder, CommandType.commandTypeClipboard, "\"${easyshell:resource_loc}\"${easyshell:line_separator}")); // Linux KDE Konsole - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "KDE Konsole", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "KDE Konsole", ResourceType.resourceFileOrFolder, CommandType.commandTypeOpen, "konsole --workdir ${easyshell:container_loc}")); - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "KDE Konsole", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "KDE Konsole", ResourceType.resourceFileOrFolder, CommandType.commandTypeRun, "konsole --workdir ${easyshell:container_loc} --noclose -e ${easyshell:resource_loc}")); // Linux Konqueror - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Konqueror", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Konqueror", ResourceType.resourceFileOrFolder, CommandType.commandTypeExplore, "konqueror file:\"${easyshell:resource_loc}\"")); // Linux Gnome Terminal - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Gnome Terminal", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Gnome Terminal", ResourceType.resourceFileOrFolder, CommandType.commandTypeOpen, "gnome-terminal --working-directory=${easyshell:container_loc}")); - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Gnome Terminal", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Gnome Terminal", ResourceType.resourceFileOrFolder, CommandType.commandTypeRun, "gnome-terminal --working-directory=${easyshell:container_loc} --command=./''${easyshell:resource_name}''")); // Linux Xfce Terminal - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Xfce Terminal", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Xfce Terminal", ResourceType.resourceFileOrFolder, CommandType.commandTypeOpen, "xfce4-terminal --working-directory=${easyshell:container_loc}")); - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Xfce Terminal", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Xfce Terminal", ResourceType.resourceFileOrFolder, CommandType.commandTypeRun, "xfce4-terminal --working-directory=${easyshell:container_loc} --command=./''${easyshell:resource_name}'' --hold")); // Linux Nautilus - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Nautilus", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Nautilus", ResourceType.resourceFileOrFolder, CommandType.commandTypeExplore, "nautilus ${easyshell:resource_loc}")); // Linux Dolphin - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Dolphin", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Dolphin", ResourceType.resourceFileOrFolder, CommandType.commandTypeExplore, "dolphin --select ${easyshell:resource_loc}")); // Linux Nemo - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Nemo", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Nemo", ResourceType.resourceFileOrFolder, CommandType.commandTypeExplore, "nemo ${easyshell:resource_loc}")); // Linux Thunar - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Thunar", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Thunar", ResourceType.resourceFileOrFolder, CommandType.commandTypeExplore, "thunar ${easyshell:resource_loc}")); // Linux Clipboard - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Full path", RessourceType.ressourceFileOrFolder, CommandType.commandTypeClipboard, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Full path", ResourceType.resourceFileOrFolder, CommandType.commandTypeClipboard, "${easyshell:resource_loc}${easyshell:line_separator}")); // MAC OS X Terminal - list.add(new CommandData(PresetType.presetPlugin, OS.osMacOSX, "Terminal", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osMacOSX, "Terminal", ResourceType.resourceFileOrFolder, CommandType.commandTypeOpen, "open -a Terminal ${easyshell:container_loc}")); - list.add(new CommandData(PresetType.presetPlugin, OS.osMacOSX, "Terminal", RessourceType.ressourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osMacOSX, "Terminal", ResourceType.resourceFileOrFolder, CommandType.commandTypeRun, "open -a Terminal ${easyshell:container_loc}")); // MAC OS X Finder - list.add(new CommandData(PresetType.presetPlugin, OS.osMacOSX, "Finder", RessourceType.ressourceFileOrFolder, CommandType.commandTypeExplore, + list.add(new CommandData(PresetType.presetPlugin, OS.osMacOSX, "Finder", ResourceType.resourceFileOrFolder, CommandType.commandTypeExplore, "open -R ${easyshell:resource_loc}")); // MAC OS X Clipboard - list.add(new CommandData(PresetType.presetPlugin, OS.osMacOSX, "Full path", RessourceType.ressourceFileOrFolder, CommandType.commandTypeClipboard, + list.add(new CommandData(PresetType.presetPlugin, OS.osMacOSX, "Full path", ResourceType.resourceFileOrFolder, CommandType.commandTypeClipboard, "${easyshell:resource_loc}${easyshell:line_separator}")); } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java index 26ffda16..9fea1088 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java @@ -11,12 +11,9 @@ package de.anbos.eclipse.easyshell.plugin.preferences; -import java.util.List; - import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.StatusDialog; import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.CCombo; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseListener; @@ -24,6 +21,7 @@ import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; @@ -38,8 +36,9 @@ public class CommandDataDialog extends StatusDialog { private CommandData data; + private Combo resourceTypeCombo; + private Combo commandTypeCombo; private Text nameText; - private CCombo typeCombo; private Text valueText; public CommandDataDialog(Shell parent, CommandData data, boolean edit) { @@ -87,8 +86,10 @@ public Control createDialogArea(Composite parent) { GridData data1 = new GridData(GridData.FILL_HORIZONTAL); pageGroup1.setLayoutData(data1); pageGroup1.setFont(parent.getFont()); - // create type type combo - createTypeCombo(pageGroup1); + // create resource type combo + createResourceTypeCombo(pageGroup1); + // create command type combo + createCommandTypeCombo(pageGroup1); //create input nameText field nameText = createTextField(pageGroup1, Activator.getResourceString("easyshell.command.editor.dialog.label.name"), data.getName()); // create input valueText field @@ -116,7 +117,9 @@ public Control createDialogArea(Composite parent) { createLabel(pageGroup2, "${easyshell:project_name}", "is the project name"); createLabel(pageGroup2, "${easyshell:line_separator}", "is the line separator"); - refreshTypeCombo(); + refreshResourceTypeCombo(); + + refreshCommandTypeCombo(); return pageComponent; } @@ -157,18 +160,26 @@ public void mouseDoubleClick(MouseEvent e) { label.setText(labelText); } - private void refreshTypeCombo() { + private void refreshResourceTypeCombo() { + // send event to refresh + Event event = new Event(); + event.item = null; + resourceTypeCombo.notifyListeners(SWT.Selection, event); + } + + private void refreshCommandTypeCombo() { // send event to refresh Event event = new Event(); event.item = null; - typeCombo.notifyListeners(SWT.Selection, event); + commandTypeCombo.notifyListeners(SWT.Selection, event); } protected void okPressed() { if (!validateValues()) { return; } - data.setCommandType(CommandType.getFromName(typeCombo.getText())); + data.setResourceType(ResourceType.getFromName(resourceTypeCombo.getText())); + data.setCommandType(CommandType.getFromName(commandTypeCombo.getText())); data.setName(nameText.getText()); data.setCommand(valueText.getText()); super.okPressed(); @@ -178,8 +189,14 @@ private boolean validateValues() { final String title = Activator.getResourceString("easyshell.command.editor.dialog.error.title.incompletedata"); + // check resource + if ( (resourceTypeCombo.getText() == null) || (resourceTypeCombo.getText().length() <= 0)) { + MessageDialog.openError(getShell(), title, Activator.getResourceString("easyshell.command.editor.dialog.error.text.resource")); + return false; + } + // check type - if ( (typeCombo.getText() == null) || (typeCombo.getText().length() <= 0)) { + if ( (commandTypeCombo.getText() == null) || (commandTypeCombo.getText().length() <= 0)) { MessageDialog.openError(getShell(), title, Activator.getResourceString("easyshell.command.editor.dialog.error.text.type")); return false; } @@ -207,40 +224,61 @@ private boolean validateValues() { return valid; } - private String[] getAllCommandTypesAsComboNames() { - List list = CommandType.getNamesAsList(); - String[] arr = new String[list.size()]; - for (int i=0;i getNamesAsList() { } return list; } + public static String[] getNamesAsArray() { + List list = getNamesAsList(); + String[] arr = new String[list.size()]; + for (int i=0;i getIconsAsList() { List list = new ArrayList(); for(int i = 0; i < CommandType.values().length; i++) { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java index 0ac767df..d44b7e57 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java @@ -18,7 +18,6 @@ import org.eclipse.jface.dialogs.StatusDialog; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.CCombo; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; @@ -26,6 +25,7 @@ import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; @@ -45,7 +45,7 @@ public class MenuDataDialog extends StatusDialog { private Button enabledCheckBox; private Text nameText; private Text commandText; - private CCombo commandCombo; + private Combo commandCombo; private Button addNewButton; private Button addCopyButton; @@ -214,7 +214,7 @@ private void removeCommand(int index, CommandData data) { } private void addNewDialog() { - CommandData data = new CommandData(PresetType.presetUser, Utils.getOS(), "MyNewCommand", RessourceType.ressourceFileOrFolder, CommandType.commandTypeOther, "my_new_command"); + CommandData data = new CommandData(PresetType.presetUser, Utils.getOS(), "MyNewCommand", ResourceType.resourceFileOrFolder, CommandType.commandTypeOther, "my_new_command"); addDialog(data); } @@ -318,9 +318,9 @@ private void createCommandCombo(Composite parent) { comboLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END)); comboLabel.setText(Activator.getResourceString("easyshell.menu.editor.dialog.label.combo")); //$NON-NLS-1$ // draw combo - commandCombo = new CCombo(parent,SWT.BORDER); + commandCombo = new Combo(parent,SWT.BORDER | SWT.READ_ONLY); commandCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - commandCombo.setEditable(false); + //commandCombo.setEditable(false); commandCombo.setItems(getAllCommandsAsComboNames(cmdList)); commandCombo.select(0); commandCombo.addSelectionListener(new SelectionListener() { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/ResourceType.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/ResourceType.java new file mode 100644 index 00000000..62dfc84b --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/ResourceType.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +import java.util.ArrayList; +import java.util.List; + +public enum ResourceType { + resourceTypeUnknown(-1, "Unknown"), + resourceTypeFile(0, "File"), + resourceTypeFolder(1, "Folder"), + resourceFileOrFolder(2, "File or Folder"); + // attributes + private final int id; + private final String name; + // construct + ResourceType(int id, String name) { + this.id = id; + this.name = name; + } + public int getId() { + return id; + } + public String getName() { + return name; + } + public static ResourceType getFromId(int id) { + ResourceType ret = resourceTypeUnknown; + for(int i = 0; i < ResourceType.values().length; i++) { + if (ResourceType.values()[i].getId() == id) { + ret = ResourceType.values()[i]; + break; + } + } + return ret; + } + public static ResourceType getFromName(String name) { + ResourceType ret = resourceTypeUnknown; + for(int i = 0; i < ResourceType.values().length; i++) { + if (ResourceType.values()[i].getName().equals(name)) { + ret = ResourceType.values()[i]; + break; + } + } + return ret; + } + public static ResourceType getFromEnum(String name) { + ResourceType ret = resourceTypeUnknown; + for(int i = 0; i < ResourceType.values().length; i++) { + if (ResourceType.values()[i].toString().equals(name)) { + ret = ResourceType.values()[i]; + break; + } + } + return ret; + } + public static List getNamesAsList() { + List list = new ArrayList(); + for(int i = 0; i < ResourceType.values().length; i++) { + if (ResourceType.values()[i] != resourceTypeUnknown) { + list.add(ResourceType.values()[i].getName()); + } + } + return list; + } + public static String[] getNamesAsArray() { + List list = getNamesAsList(); + String[] arr = new String[list.size()]; + for (int i=0;i getNamesAsList() { - List list = new ArrayList(); - for(int i = 0; i < RessourceType.values().length; i++) { - if (RessourceType.values()[i] != ressourceTypeUnknown) { - list.add(RessourceType.values()[i].getName()); - } - } - return list; - } -} \ No newline at end of file From 0edebdce568682b3710a72def4cd3a7ec42144bd Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Wed, 13 Jul 2016 08:46:07 +0200 Subject: [PATCH 07/73] refactoring: moved internal types to own package Signed-off-by: Andre Bossert --- .../src/de/anbos/eclipse/easyshell/plugin/Activator.java | 3 +-- .../easyshell/plugin/{preferences => }/Constants.java | 2 +- .../eclipse/easyshell/plugin/{preferences => }/Utils.java | 5 ++++- .../eclipse/easyshell/plugin/actions/ActionDelegate.java | 6 +++--- .../eclipse/easyshell/plugin/handlers/CommandHandler.java | 2 +- .../eclipse/easyshell/plugin/preferences/CommandData.java | 5 +++++ .../plugin/preferences/CommandDataDefaultCollection.java | 7 +++++++ .../easyshell/plugin/preferences/CommandDataDialog.java | 3 +++ .../easyshell/plugin/preferences/CommandDataStore.java | 2 ++ .../eclipse/easyshell/plugin/preferences/Initializer.java | 1 + .../easyshell/plugin/preferences/MenuDataDialog.java | 4 ++++ .../easyshell/plugin/preferences/MenuDataStore.java | 2 ++ .../plugin/{preferences => types}/CommandType.java | 4 +++- .../easyshell/plugin/{preferences => types}/Debug.java | 2 +- .../plugin/{preferences => types}/LinuxDesktop.java | 2 +- .../easyshell/plugin/{preferences => types}/OS.java | 2 +- .../plugin/{preferences => types}/PresetType.java | 2 +- .../easyshell/plugin/{preferences => types}/Quotes.java | 2 +- .../plugin/{preferences => types}/ResourceType.java | 2 +- .../easyshell/plugin/{preferences => types}/Tokenizer.java | 2 +- 20 files changed, 44 insertions(+), 16 deletions(-) rename plugin/src/de/anbos/eclipse/easyshell/plugin/{preferences => }/Constants.java (97%) rename plugin/src/de/anbos/eclipse/easyshell/plugin/{preferences => }/Utils.java (97%) rename plugin/src/de/anbos/eclipse/easyshell/plugin/{preferences => types}/CommandType.java (97%) rename plugin/src/de/anbos/eclipse/easyshell/plugin/{preferences => types}/Debug.java (97%) rename plugin/src/de/anbos/eclipse/easyshell/plugin/{preferences => types}/LinuxDesktop.java (97%) rename plugin/src/de/anbos/eclipse/easyshell/plugin/{preferences => types}/OS.java (97%) rename plugin/src/de/anbos/eclipse/easyshell/plugin/{preferences => types}/PresetType.java (97%) rename plugin/src/de/anbos/eclipse/easyshell/plugin/{preferences => types}/Quotes.java (97%) rename plugin/src/de/anbos/eclipse/easyshell/plugin/{preferences => types}/ResourceType.java (98%) rename plugin/src/de/anbos/eclipse/easyshell/plugin/{preferences => types}/Tokenizer.java (97%) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java index ac2e4bef..bf768339 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java @@ -26,8 +26,7 @@ import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; -import de.anbos.eclipse.easyshell.plugin.preferences.Constants; -import de.anbos.eclipse.easyshell.plugin.preferences.CommandType; +import de.anbos.eclipse.easyshell.plugin.types.CommandType; /** * The activator class controls the plug-in life cycle diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Constants.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/Constants.java similarity index 97% rename from plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Constants.java rename to plugin/src/de/anbos/eclipse/easyshell/plugin/Constants.java index aff1e5c0..64a00423 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Constants.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/Constants.java @@ -9,7 +9,7 @@ * Andre Bossert - initial API and implementation and/or initial documentation *******************************************************************************/ -package de.anbos.eclipse.easyshell.plugin.preferences; +package de.anbos.eclipse.easyshell.plugin; public interface Constants { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Utils.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/Utils.java similarity index 97% rename from plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Utils.java rename to plugin/src/de/anbos/eclipse/easyshell/plugin/Utils.java index 6f42b369..55463eca 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Utils.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/Utils.java @@ -9,7 +9,7 @@ * Andre Bossert - initial API and implementation and/or initial documentation *******************************************************************************/ -package de.anbos.eclipse.easyshell.plugin.preferences; +package de.anbos.eclipse.easyshell.plugin; import java.io.BufferedReader; import java.io.InputStreamReader; @@ -25,6 +25,9 @@ import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.ToolTip; +import de.anbos.eclipse.easyshell.plugin.types.LinuxDesktop; +import de.anbos.eclipse.easyshell.plugin.types.OS; + public class Utils { public static OS getOS() { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java index 7e3e9eef..28cc32c8 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java @@ -28,9 +28,9 @@ import de.anbos.eclipse.easyshell.plugin.DynamicVariableResolver; import de.anbos.eclipse.easyshell.plugin.Resource; import de.anbos.eclipse.easyshell.plugin.ResourceUtils; -import de.anbos.eclipse.easyshell.plugin.preferences.CommandType; -import de.anbos.eclipse.easyshell.plugin.preferences.Quotes; -import de.anbos.eclipse.easyshell.plugin.preferences.Utils; +import de.anbos.eclipse.easyshell.plugin.Utils; +import de.anbos.eclipse.easyshell.plugin.types.CommandType; +import de.anbos.eclipse.easyshell.plugin.types.Quotes; public class ActionDelegate implements IObjectActionDelegate { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/CommandHandler.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/CommandHandler.java index 1f07f69d..bb00284a 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/CommandHandler.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/CommandHandler.java @@ -21,7 +21,7 @@ import de.anbos.eclipse.easyshell.plugin.EditorPropertyTester; import de.anbos.eclipse.easyshell.plugin.actions.Action; import de.anbos.eclipse.easyshell.plugin.actions.ActionDelegate; -import de.anbos.eclipse.easyshell.plugin.preferences.CommandType; +import de.anbos.eclipse.easyshell.plugin.types.CommandType; public class CommandHandler extends AbstractHandler { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java index cc4493e7..1e1a0ba0 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java @@ -14,6 +14,11 @@ import java.util.StringTokenizer; import java.util.UUID; +import de.anbos.eclipse.easyshell.plugin.types.CommandType; +import de.anbos.eclipse.easyshell.plugin.types.OS; +import de.anbos.eclipse.easyshell.plugin.types.PresetType; +import de.anbos.eclipse.easyshell.plugin.types.ResourceType; + public class CommandData { // internal diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java index b7b249b5..67532b47 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java @@ -14,6 +14,13 @@ import java.util.ArrayList; import java.util.List; +import de.anbos.eclipse.easyshell.plugin.Utils; +import de.anbos.eclipse.easyshell.plugin.types.CommandType; +import de.anbos.eclipse.easyshell.plugin.types.LinuxDesktop; +import de.anbos.eclipse.easyshell.plugin.types.OS; +import de.anbos.eclipse.easyshell.plugin.types.PresetType; +import de.anbos.eclipse.easyshell.plugin.types.ResourceType; + public class CommandDataDefaultCollection { private List list = new ArrayList(); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java index 9fea1088..8d36b423 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java @@ -31,6 +31,9 @@ import org.eclipse.swt.widgets.Text; import de.anbos.eclipse.easyshell.plugin.Activator; +import de.anbos.eclipse.easyshell.plugin.Utils; +import de.anbos.eclipse.easyshell.plugin.types.CommandType; +import de.anbos.eclipse.easyshell.plugin.types.ResourceType; public class CommandDataDialog extends StatusDialog { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataStore.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataStore.java index f7a36361..78028635 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataStore.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataStore.java @@ -18,6 +18,8 @@ import org.eclipse.jface.preference.IPreferenceStore; +import de.anbos.eclipse.easyshell.plugin.Constants; + public class CommandDataStore { private IPreferenceStore store; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java index e42c9218..3ce6c9c5 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java @@ -15,6 +15,7 @@ import org.eclipse.jface.preference.IPreferenceStore; import de.anbos.eclipse.easyshell.plugin.Activator; +import de.anbos.eclipse.easyshell.plugin.Constants; public class Initializer extends AbstractPreferenceInitializer { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java index d44b7e57..9ef54ce0 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java @@ -35,6 +35,10 @@ import org.eclipse.swt.widgets.Text; import de.anbos.eclipse.easyshell.plugin.Activator; +import de.anbos.eclipse.easyshell.plugin.Utils; +import de.anbos.eclipse.easyshell.plugin.types.CommandType; +import de.anbos.eclipse.easyshell.plugin.types.PresetType; +import de.anbos.eclipse.easyshell.plugin.types.ResourceType; public class MenuDataDialog extends StatusDialog { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java index afd1d6f5..05c7486c 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java @@ -19,6 +19,8 @@ import org.eclipse.jface.preference.IPreferenceStore; +import de.anbos.eclipse.easyshell.plugin.Constants; + public class MenuDataStore { private IPreferenceStore store; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandType.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/CommandType.java similarity index 97% rename from plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandType.java rename to plugin/src/de/anbos/eclipse/easyshell/plugin/types/CommandType.java index c3e4b3e8..1a69e784 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandType.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/CommandType.java @@ -9,11 +9,13 @@ * Andre Bossert - initial API and implementation and/or initial documentation *******************************************************************************/ -package de.anbos.eclipse.easyshell.plugin.preferences; +package de.anbos.eclipse.easyshell.plugin.types; import java.util.ArrayList; import java.util.List; +import de.anbos.eclipse.easyshell.plugin.Constants; + public enum CommandType { commandTypeUnknown(-1, "Unknown", Constants.IMAGE_UNKNOWN, Constants.ACTION_UNKNOWN), commandTypeOpen(0, "Open", Constants.IMAGE_OPEN, Constants.ACTION_OPEN), diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Debug.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Debug.java similarity index 97% rename from plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Debug.java rename to plugin/src/de/anbos/eclipse/easyshell/plugin/types/Debug.java index ed88266d..de387ad3 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Debug.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Debug.java @@ -9,7 +9,7 @@ * Andre Bossert - initial API and implementation and/or initial documentation *******************************************************************************/ -package de.anbos.eclipse.easyshell.plugin.preferences; +package de.anbos.eclipse.easyshell.plugin.types; /** * Debug. diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/LinuxDesktop.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/LinuxDesktop.java similarity index 97% rename from plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/LinuxDesktop.java rename to plugin/src/de/anbos/eclipse/easyshell/plugin/types/LinuxDesktop.java index 26980d64..acbce651 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/LinuxDesktop.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/LinuxDesktop.java @@ -9,7 +9,7 @@ * Andre Bossert - initial API and implementation and/or initial documentation *******************************************************************************/ -package de.anbos.eclipse.easyshell.plugin.preferences; +package de.anbos.eclipse.easyshell.plugin.types; /** * Linux desktops. diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/OS.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/OS.java similarity index 97% rename from plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/OS.java rename to plugin/src/de/anbos/eclipse/easyshell/plugin/types/OS.java index dac1c722..1bfc32c6 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/OS.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/OS.java @@ -9,7 +9,7 @@ * Andre Bossert - initial API and implementation and/or initial documentation *******************************************************************************/ -package de.anbos.eclipse.easyshell.plugin.preferences; +package de.anbos.eclipse.easyshell.plugin.types; import java.util.ArrayList; import java.util.List; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetType.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/PresetType.java similarity index 97% rename from plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetType.java rename to plugin/src/de/anbos/eclipse/easyshell/plugin/types/PresetType.java index e49c1619..d8bc0f18 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PresetType.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/PresetType.java @@ -9,7 +9,7 @@ * Andre Bossert - initial API and implementation and/or initial documentation *******************************************************************************/ -package de.anbos.eclipse.easyshell.plugin.preferences; +package de.anbos.eclipse.easyshell.plugin.types; import java.util.ArrayList; import java.util.List; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Quotes.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Quotes.java similarity index 97% rename from plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Quotes.java rename to plugin/src/de/anbos/eclipse/easyshell/plugin/types/Quotes.java index 44d501f8..d69ac08d 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Quotes.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Quotes.java @@ -16,7 +16,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package de.anbos.eclipse.easyshell.plugin.preferences; +package de.anbos.eclipse.easyshell.plugin.types; /** * Quotes. diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/ResourceType.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/ResourceType.java similarity index 98% rename from plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/ResourceType.java rename to plugin/src/de/anbos/eclipse/easyshell/plugin/types/ResourceType.java index 62dfc84b..559af676 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/ResourceType.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/ResourceType.java @@ -9,7 +9,7 @@ * Andre Bossert - initial API and implementation and/or initial documentation *******************************************************************************/ -package de.anbos.eclipse.easyshell.plugin.preferences; +package de.anbos.eclipse.easyshell.plugin.types; import java.util.ArrayList; import java.util.List; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Tokenizer.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Tokenizer.java similarity index 97% rename from plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Tokenizer.java rename to plugin/src/de/anbos/eclipse/easyshell/plugin/types/Tokenizer.java index 475165b1..cf4ea3a0 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Tokenizer.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Tokenizer.java @@ -9,7 +9,7 @@ * Andre Bossert - initial API and implementation and/or initial documentation *******************************************************************************/ -package de.anbos.eclipse.easyshell.plugin.preferences; +package de.anbos.eclipse.easyshell.plugin.types; public enum Tokenizer { tokenizerUnknown(-1, "Unknown"), From c8d17ae9d1bf9adc26af51d2bfd9b7fc5a921539 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Wed, 13 Jul 2016 10:22:09 +0200 Subject: [PATCH 08/73] added logging and fixed variable copy to clipboard Signed-off-by: Andre Bossert --- .../eclipse/easyshell/plugin/Activator.java | 78 +++++++++++++++++++ .../easyshell/plugin/UIMessages.properties | 7 +- .../anbos/eclipse/easyshell/plugin/Utils.java | 24 +++++- .../plugin/actions/ActionDelegate.java | 22 +----- .../plugin/preferences/CommandDataDialog.java | 4 +- 5 files changed, 110 insertions(+), 25 deletions(-) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java index bf768339..6e2acab1 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java @@ -20,12 +20,14 @@ import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.resource.ImageRegistry; import org.eclipse.ui.plugin.AbstractUIPlugin; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; + import de.anbos.eclipse.easyshell.plugin.types.CommandType; /** @@ -125,4 +127,80 @@ public static String getResourceString(String key, Object[] args) { return MessageFormat.format(getResourceString(key),args); } + public void log(String msg) { + log(null, msg, null); + } + + public void log(String msg, Exception e) { + logInfo(null, msg, e, false); + } + + public void log(String title, String msg, Exception e) { + logInfo(title, msg, e, false); + } + + public void logSuccess(String title, String msg, Exception e, boolean tooltip) { + log(Status.OK, title != null ? title + ": " + msg : msg, e); + if (tooltip) { + tooltipSuccess(getResourceString("easyshell.plugin.name") + ": " + title, msg); + } + } + + public void logInfo(String title, String msg, Exception e, boolean tooltip) { + log(Status.INFO, title != null ? title + ": " + msg : msg, e); + if (tooltip) { + tooltipInfo(getResourceString("easyshell.plugin.name") + ": " + title, msg); + } + } + + public void logWarning(String title, String msg, Exception e, boolean tooltip) { + log(Status.WARNING, title != null ? title + ": " + msg : msg, e); + if (tooltip) { + tooltipWarning(getResourceString("easyshell.plugin.name") + ": " + title, msg); + } + } + + public void logError(String title, String msg, Exception e, boolean tooltip) { + log(Status.ERROR, title != null ? title + ": " + msg : msg, e); + if (tooltip) { + tooltipError(getResourceString("easyshell.plugin.name") + ": " + title, msg); + } + } + + public void logSuccess(String msg, Exception e) { + logSuccess(null, msg, null, false); + } + + public void logInfo(String msg, Exception e) { + logInfo(null, msg, null, false); + } + + public void logWarning(String msg, Exception e) { + logWarning(null, msg, null, false); + } + + public void logError(String msg, Exception e) { + logError(null, msg, null, false); + } + + public void log(int status, String msg, Exception e) { + getLog().log(new Status(status, Constants.PLUGIN_ID, Status.OK, msg, e)); + } + + public void tooltipSuccess(String title, String msg) { + Utils.showToolTipSuccess(null, getResourceString("easyshell.plugin.name") + ": " + title, msg); + } + + public void tooltipInfo(String title, String msg) { + Utils.showToolTipInfo(null, getResourceString("easyshell.plugin.name") + ": " + title, msg); + } + + public void tooltipWarning(String title, String msg) { + Utils.showToolTipWarning(null, getResourceString("easyshell.plugin.name") + ": " + title, msg); + } + + public void tooltipError(String title, String msg) { + Utils.showToolTipError(null, getResourceString("easyshell.plugin.name") + ": " + title, msg); + } + } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties index 4c621923..03c003da 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties @@ -2,7 +2,10 @@ easyshell.plugin.name=EasyShell easyshell.properties.main.page.title=EasyShell easyshell.properties.commands.page.title=Presets easyshell.actionset.name=EasyShell -easyshell.message.copytoclipboard=copied to clipboard + +easyshell.message.copytoclipboard=Copied to clipboard +easyshell.message.error.internal=Unable to open shell +easyshell.message.error.exec=Execute error easyshell.page.table.header.title.column0=Name easyshell.page.table.header.title.column1=Command @@ -46,7 +49,7 @@ easyshell.command.editor.dialog.title.edit=Edit existing command easyshell.command.editor.dialog.title.group1=Command definition easyshell.command.editor.dialog.tooltip.group1=Add your command here easyshell.command.editor.dialog.title.group2=Usable variables -easyshell.command.editor.dialog.tooltip.group2=Double click at variables to copy them to clipboard +easyshell.command.editor.dialog.tooltip.group2=Double click at variable copies it to clipboard easyshell.command.editor.dialog.error.title.incompletedata=Missing or wrong command detected easyshell.command.editor.dialog.error.text.resource=Please choose a valid resource type easyshell.command.editor.dialog.error.text.type=Please choose a valid command type diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/Utils.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/Utils.java index 55463eca..de1635a7 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/Utils.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/Utils.java @@ -198,13 +198,31 @@ public static void copyToClipboard(String cmdAll) { clipboard.dispose(); } - public static void showToolTip(Control control, String title, String message) { - ToolTip tooltip = new ToolTip(control.getShell(), /*SWT.BALLOON | */SWT.ICON_INFORMATION); + public static void showToolTipSuccess(Control control, String title, String message) { + showToolTip(control, SWT.ICON_WORKING, title, message); + } + + public static void showToolTipInfo(Control control, String title, String message) { + showToolTip(control, SWT.ICON_INFORMATION, title, message); + } + + public static void showToolTipWarning(Control control, String title, String message) { + showToolTip(control, SWT.ICON_WARNING, title, message); + } + + public static void showToolTipError(Control control, String title, String message) { + showToolTip(control, SWT.ICON_ERROR, title, message); + } + + public static void showToolTip(Control control, int style, String title, String message) { + if (control == null) { + control = Display.getDefault().getActiveShell(); + } + ToolTip tooltip = new ToolTip(control.getShell(), /*SWT.BALLOON | */ style); tooltip.setAutoHide(true); tooltip.setLocation(control.toDisplay(control.getSize().x/2, control.getSize().y + 5)); tooltip.setText(title); tooltip.setMessage(message); tooltip.setVisible(true); } - } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java index 28cc32c8..642848fd 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java @@ -16,11 +16,8 @@ import org.eclipse.core.variables.IStringVariableManager; import org.eclipse.core.variables.VariablesPlugin; import org.eclipse.jface.action.IAction; -import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IObjectActionDelegate; import org.eclipse.ui.IWorkbenchPart; @@ -64,11 +61,7 @@ public void setActivePart(IAction action, IWorkbenchPart targetPart) { public void run(IAction action) { if (!isEnabled()) { - MessageDialog.openInformation( - new Shell(), - "Easy Shell", - "Wrong Selection"); - //Activator.log("Wrong Selection"); + Activator.getDefault().logError("Wrong Selection", null); return; } @@ -169,25 +162,18 @@ public void run(IAction action) { } } catch (Exception e) { - //Activator.log(e); + Activator.getDefault().logError(Activator.getResourceString("easyshell.message.error.exec"), commandValue, e, true); } } else { - - MessageDialog.openInformation( - new Shell(), - "Easy Shell", - "Unable to open shell"); - //Activator.log("Unable to open shell"); - return; - + Activator.getDefault().logError(Activator.getResourceString("easyshell.message.error.internal"), commandValue, null, true); } } // handling copy to clipboard if ((commandType == CommandType.commandTypeClipboard) && (cmdAll != null) && (cmdAll.length() != 0)) { Utils.copyToClipboard(cmdAll); - Utils.showToolTip(Display.getDefault().getActiveShell(), Activator.getResourceString("easyshell.plugin.name") + ": " + Activator.getResourceString("easyshell.message.copytoclipboard"), cmdAll); + Activator.getDefault().tooltipInfo(Activator.getResourceString("easyshell.message.copytoclipboard"), cmdAll); } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java index 8d36b423..603ecf86 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java @@ -154,8 +154,8 @@ public void mouseDoubleClick(MouseEvent e) { text.selectAll(); String title = Activator.getResourceString("easyshell.message.copytoclipboard"); String message = text.getText(); - Utils.copyToClipboard(title); - Utils.showToolTip(control, title, message); + Utils.copyToClipboard(message); + Utils.showToolTipInfo(control, title, message); text.setSelection(0, 0); } }); From f0fa493eb61c5d18c7fe7dffbfffc09bf2354cf7 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Wed, 13 Jul 2016 13:25:03 +0200 Subject: [PATCH 09/73] added variable validation and more debug logs Signed-off-by: Andre Bossert --- plugin/plugin.xml | 6 ++ .../eclipse/easyshell/plugin/Activator.java | 44 +++++++----- .../plugin/DynamicVariableResolver.java | 46 ++++++++----- .../easyshell/plugin/UIMessages.properties | 3 +- .../plugin/actions/ActionDelegate.java | 68 +++++++++++-------- .../plugin/preferences/CommandsPage.java | 1 - .../easyshell/plugin/types/Quotes.java | 25 +++---- 7 files changed, 113 insertions(+), 80 deletions(-) diff --git a/plugin/plugin.xml b/plugin/plugin.xml index 776e287a..5fc5f9e1 100644 --- a/plugin/plugin.xml +++ b/plugin/plugin.xml @@ -89,6 +89,12 @@ resolver="de.anbos.eclipse.easyshell.plugin.DynamicVariableResolver" supportsArgument="true"> + + diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java index 6e2acab1..394bbdb1 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java @@ -29,6 +29,7 @@ import de.anbos.eclipse.easyshell.plugin.types.CommandType; +import de.anbos.eclipse.easyshell.plugin.types.Debug; /** * The activator class controls the plug-in life cycle @@ -96,6 +97,7 @@ public static ImageDescriptor getImageDescriptor(String path) { public static ImageDescriptor getImageDescriptor(String id) { return getDefault().getImageRegistry().getDescriptor(id); } + protected void initializeImageRegistry(ImageRegistry registry) { Bundle bundle = Platform.getBundle(Constants.PLUGIN_ID); for (String icon : CommandType.getIconsAsList()) { @@ -127,80 +129,88 @@ public static String getResourceString(String key, Object[] args) { return MessageFormat.format(getResourceString(key),args); } - public void log(String msg) { + public static void log(String msg) { log(null, msg, null); } - public void log(String msg, Exception e) { + public static void log(String msg, Exception e) { logInfo(null, msg, e, false); } - public void log(String title, String msg, Exception e) { + public static void log(String title, String msg, Exception e) { logInfo(title, msg, e, false); } - public void logSuccess(String title, String msg, Exception e, boolean tooltip) { + public static void logSuccess(String title, String msg, Exception e, boolean tooltip) { log(Status.OK, title != null ? title + ": " + msg : msg, e); if (tooltip) { tooltipSuccess(getResourceString("easyshell.plugin.name") + ": " + title, msg); } } - public void logInfo(String title, String msg, Exception e, boolean tooltip) { + public static void logInfo(String title, String msg, Exception e, boolean tooltip) { log(Status.INFO, title != null ? title + ": " + msg : msg, e); if (tooltip) { tooltipInfo(getResourceString("easyshell.plugin.name") + ": " + title, msg); } } - public void logWarning(String title, String msg, Exception e, boolean tooltip) { + public static void logWarning(String title, String msg, Exception e, boolean tooltip) { log(Status.WARNING, title != null ? title + ": " + msg : msg, e); if (tooltip) { tooltipWarning(getResourceString("easyshell.plugin.name") + ": " + title, msg); } } - public void logError(String title, String msg, Exception e, boolean tooltip) { + public static void logError(String title, String msg, Exception e, boolean tooltip) { log(Status.ERROR, title != null ? title + ": " + msg : msg, e); if (tooltip) { tooltipError(getResourceString("easyshell.plugin.name") + ": " + title, msg); } } - public void logSuccess(String msg, Exception e) { + public static void logSuccess(String msg, Exception e) { logSuccess(null, msg, null, false); } - public void logInfo(String msg, Exception e) { + public static void logInfo(String msg, Exception e) { logInfo(null, msg, null, false); } - public void logWarning(String msg, Exception e) { + public static void logWarning(String msg, Exception e) { logWarning(null, msg, null, false); } - public void logError(String msg, Exception e) { + public static void logError(String msg, Exception e) { logError(null, msg, null, false); } - public void log(int status, String msg, Exception e) { - getLog().log(new Status(status, Constants.PLUGIN_ID, Status.OK, msg, e)); + public static void log(int status, String msg, Exception e) { + getDefault().getLog().log(new Status(status, Constants.PLUGIN_ID, Status.OK, msg, e)); } - public void tooltipSuccess(String title, String msg) { + public static void tooltipSuccess(String title, String msg) { Utils.showToolTipSuccess(null, getResourceString("easyshell.plugin.name") + ": " + title, msg); } - public void tooltipInfo(String title, String msg) { + public static void tooltipInfo(String title, String msg) { Utils.showToolTipInfo(null, getResourceString("easyshell.plugin.name") + ": " + title, msg); } - public void tooltipWarning(String title, String msg) { + public static void tooltipWarning(String title, String msg) { Utils.showToolTipWarning(null, getResourceString("easyshell.plugin.name") + ": " + title, msg); } - public void tooltipError(String title, String msg) { + public static void tooltipError(String title, String msg) { Utils.showToolTipError(null, getResourceString("easyshell.plugin.name") + ": " + title, msg); } + public static void logDebug(String string) { + // TODO: get from preferences store + Debug debug = Debug.debugNo; + if (debug == Debug.debugYes) { + log(Status.INFO, string, null); + } + } + } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/DynamicVariableResolver.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/DynamicVariableResolver.java index b5697a99..f9d289fd 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/DynamicVariableResolver.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/DynamicVariableResolver.java @@ -22,24 +22,38 @@ public class DynamicVariableResolver implements IDynamicVariableResolver { @Override public String resolveValue(IDynamicVariable variable, String argument) throws CoreException { - if (variable.getName().equals("easyshell")) { - if (argument.equals("drive")) { - return args[0]; - } else if (argument.equals("container_loc")) { - return args[1]; - } else if (argument.equals("resource_loc")) { - return args[2]; - } else if (argument.equals("resource_name")) { - return args[3]; - } else if (argument.equals("project_name")) { - return args[4]; - } else if (argument.equals("line_separator")) { - return args[5]; - } - } - return null; + // easyshell own variables + String variableName = variable.getName(); + if (variableName.equals("easyshell")) { + return handleOwnVariable(argument); + } else { + return handleEclipseVariable(variableName, argument); + } } + private String handleOwnVariable(String argument) { + if (argument.equals("drive")) { + return args[0]; + } else if (argument.equals("line_separator")) { + return args[5]; + } + // here we have eclipse variables embedded in easyshell variable as parameter + return handleEclipseVariable(argument, null); + } + + private String handleEclipseVariable(String variable, String argument) { + if (variable.equals("container_loc")) { + return args[1]; + } else if (variable.equals("resource_loc")) { + return args[2]; + } else if (variable.equals("resource_name")) { + return args[3]; + } else if (variable.equals("project_name")) { + return args[4]; + } + return null; + } + public String[] getArgs() { return args; } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties index 03c003da..eda57a1a 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties @@ -5,7 +5,8 @@ easyshell.actionset.name=EasyShell easyshell.message.copytoclipboard=Copied to clipboard easyshell.message.error.internal=Unable to open shell -easyshell.message.error.exec=Execute error +easyshell.message.error.execution=Execution error +easyshell.message.error.validation=Validation error easyshell.page.table.header.title.column0=Name easyshell.page.table.header.title.column1=Command diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java index 642848fd..a47ffc9d 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java @@ -13,6 +13,7 @@ import java.util.StringTokenizer; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.variables.IStringVariableManager; import org.eclipse.core.variables.VariablesPlugin; import org.eclipse.jface.action.IAction; @@ -28,6 +29,7 @@ import de.anbos.eclipse.easyshell.plugin.Utils; import de.anbos.eclipse.easyshell.plugin.types.CommandType; import de.anbos.eclipse.easyshell.plugin.types.Quotes; +import de.anbos.eclipse.easyshell.plugin.types.Tokenizer; public class ActionDelegate implements IObjectActionDelegate { @@ -61,13 +63,15 @@ public void setActivePart(IAction action, IWorkbenchPart targetPart) { public void run(IAction action) { if (!isEnabled()) { - Activator.getDefault().logError("Wrong Selection", null); + Activator.logError("Wrong Selection", null); return; } + /* TODO: remove // get the ID - //String ActionIDStr = action.getId(); - //Activator.getDefault().sysout(true, "Action ID: >" + ActionIDStr + "<"); + String ActionIDStr = action.getId(); + Activator.logDebug("Action ID: >" + ActionIDStr + "<"); + */ // String for all commands in case of clipboard String cmdAll = null; @@ -90,7 +94,7 @@ public void run(IAction action) { full_path = resource[i].getFile().toString(); if (resource[i].getFile().isDirectory()) { parent_path = resource[i].getFile().getPath(); - file_name = "dir"; // dummy cmd + //file_name = "dir"; // dummy cmd }else { parent_path = resource[i].getFile().getParent(); @@ -99,9 +103,9 @@ public void run(IAction action) { if (full_path != null) { - //Activator.getDefault().sysout(true, "full_path : >" + full_path + "<"); - //Activator.getDefault().sysout(true, "parent_path: >" + parent_path + "<"); - //Activator.getDefault().sysout(true, "file_name : >" + file_name + "<"); + Activator.logDebug("full_path : >" + full_path + "<"); + Activator.logDebug("parent_path: >" + parent_path + "<"); + Activator.logDebug("file_name : >" + file_name + "<"); // Try to extract drive on Win32 if (full_path.indexOf(":") != -1) { @@ -109,8 +113,8 @@ public void run(IAction action) { } try { - String target = commandValue; - //Quotes quotes = Activator.getDefault().getQuotes(InstanceIDNum); + // TODO: get from preferences store + //Quotes quotes = Activator.getQuotes(InstanceIDNum); Quotes quotes = Quotes.quotesNo; String[] args = new String[6]; // args format @@ -120,60 +124,66 @@ public void run(IAction action) { args[3] = autoQuotes(file_name, quotes); // {3} == ${easyshell:resource_name} args[4] = resource[i].getProjectName(); // {4} == ${easyshell:project_name} if (args[4] == null) - args[4] = "EasyShell"; + args[4] = Activator.getResourceString("easyshell.plugin.name"); args[5] = System.getProperty("line.separator"); // {5} == ${easyshell:line_separator} // variable format DynamicVariableResolver.setArgs(args); + variableManager.validateStringVariables(commandValue); + Activator.logDebug(commandValue); // handling copy to clipboard if (commandType == CommandType.commandTypeClipboard) { - String cmd = fixQuotes(variableManager.performStringSubstitution(target, false), quotes); - //Activator.getDefault().sysout(true, "--- clp: >"); + String cmd = fixQuotes(variableManager.performStringSubstitution(commandValue, false), quotes); + Activator.logDebug("--- clp: >"); cmdAll += cmd; - //Activator.getDefault().sysout(true, cmd); - //Activator.getDefault().sysout(true, "--- clp: <"); + Activator.logDebug(cmd); + Activator.logDebug("--- clp: <"); } // handling command line else { // string tokenizer enabled ? - //if (Activator.getDefault().isTokenizer(InstanceIDNum)) - if (true) + // TODO: get from preferences store + //Tokenizer tokenizer = Activator.isTokenizer(InstanceIDNum); + Tokenizer tokenizer = Tokenizer.tokenizerYes; + if (tokenizer == Tokenizer.tokenizerYes) { - StringTokenizer st = new StringTokenizer(target); + StringTokenizer st = new StringTokenizer(commandValue); String[] cmds = new String[st.countTokens()]; int c = 0; - //Activator.getDefault().sysout(true, "--- cmd: >"); + Activator.logDebug("--- cmd: >"); while (st.hasMoreElements()) { cmds[c] = fixQuotes(variableManager.performStringSubstitution(st.nextToken(), false), quotes); - //Activator.getDefault().sysout(true, cmds[c]); + Activator.logDebug(cmds[c]); c++; } - //Activator.getDefault().sysout(true, "--- cmd: <"); - //Utils.showToolTip(Display.getDefault().getActiveShell(), "EasyShell: executed", target); + Activator.logDebug("--- cmd: <"); + //Utils.showToolTip(Display.getDefault().getActiveShell(), "EasyShell: executed", commandValue); + // ---------- RUN -------------- Runtime.getRuntime().exec(cmds); } // the old command line passing without string tokenizer else { - String cmd = fixQuotes(variableManager.performStringSubstitution(target, false), quotes); - //Activator.getDefault().sysout(true, "--- cmd: >"); + String cmd = fixQuotes(variableManager.performStringSubstitution(commandValue, false), quotes); + Activator.logDebug("--- cmd: >"); + Activator.logDebug(cmd); + Activator.logDebug("--- cmd: <"); Runtime.getRuntime().exec(cmd); - //Activator.getDefault().sysout(true, cmd); - //Activator.getDefault().sysout(true, "--- cmd: <"); } } - + } catch (CoreException e) { + Activator.logError(Activator.getResourceString("easyshell.message.error.validation"), commandValue, e, true); } catch (Exception e) { - Activator.getDefault().logError(Activator.getResourceString("easyshell.message.error.exec"), commandValue, e, true); + Activator.logError(Activator.getResourceString("easyshell.message.error.execution"), commandValue, e, true); } } else { - Activator.getDefault().logError(Activator.getResourceString("easyshell.message.error.internal"), commandValue, null, true); + Activator.logError(Activator.getResourceString("easyshell.message.error.internal"), commandValue, null, true); } } // handling copy to clipboard if ((commandType == CommandType.commandTypeClipboard) && (cmdAll != null) && (cmdAll.length() != 0)) { Utils.copyToClipboard(cmdAll); - Activator.getDefault().tooltipInfo(Activator.getResourceString("easyshell.message.copytoclipboard"), cmdAll); + Activator.tooltipInfo(Activator.getResourceString("easyshell.message.copytoclipboard"), cmdAll); } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsPage.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsPage.java index 1caa55da..a5dd8793 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsPage.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsPage.java @@ -11,7 +11,6 @@ package de.anbos.eclipse.easyshell.plugin.preferences; -import java.text.MessageFormat; import java.util.Iterator; import java.util.List; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Quotes.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Quotes.java index d69ac08d..4a1fec67 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Quotes.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Quotes.java @@ -1,20 +1,13 @@ -/* - * Copyright (C) 2014 - 2016 by Andre Bossert +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ package de.anbos.eclipse.easyshell.plugin.types; From 44b20a0918ee52fca209b21a34a32b99d84d05ed Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Wed, 13 Jul 2016 18:55:23 +0200 Subject: [PATCH 10/73] removed UUID from preferences and reworked default loading Signed-off-by: Andre Bossert --- plugin/plugin.xml | 6 --- .../plugin/preferences/CommandData.java | 4 +- .../CommandDataDefaultCollection.java | 42 +++++++++++++------ .../plugin/preferences/CommandsPage.java | 5 +-- .../plugin/preferences/Initializer.java | 4 +- .../plugin/preferences/MenuData.java | 6 +-- .../preferences/MenuDataContentProvider.java | 8 +--- .../plugin/preferences/MenuDataStore.java | 2 +- 8 files changed, 39 insertions(+), 38 deletions(-) diff --git a/plugin/plugin.xml b/plugin/plugin.xml index 5fc5f9e1..776e287a 100644 --- a/plugin/plugin.xml +++ b/plugin/plugin.xml @@ -89,12 +89,6 @@ resolver="de.anbos.eclipse.easyshell.plugin.DynamicVariableResolver" supportsArgument="true"> - - diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java index 1e1a0ba0..d5c8ec5f 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java @@ -146,7 +146,7 @@ public boolean deserialize(String value, StringTokenizer tokenizer, String delim } // set members setPosition(Integer.parseInt(tokenizer.nextToken())); - setId(tokenizer.nextToken()); + //setId(tokenizer.nextToken()); setPresetType(PresetType.getFromEnum(tokenizer.nextToken())); setOs(OS.getFromEnum(tokenizer.nextToken())); setName(tokenizer.nextToken()); @@ -157,7 +157,7 @@ public boolean deserialize(String value, StringTokenizer tokenizer, String delim } public String serialize(String delimiter) { - return Integer.toString(getPosition()) + delimiter + getId() + delimiter + getPresetType().toString() + delimiter + getOS().toString() + delimiter + getName() + delimiter + getResourceType().toString() + delimiter + getCommandType().toString() + delimiter + getCommand() + delimiter; + return Integer.toString(getPosition()) + delimiter + /*getId() + delimiter +*/ getPresetType().toString() + delimiter + getOS().toString() + delimiter + getName() + delimiter + getResourceType().toString() + delimiter + getCommandType().toString() + delimiter + getCommand() + delimiter; } public String getTypeIcon() { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java index 67532b47..62f1388f 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java @@ -26,19 +26,29 @@ public class CommandDataDefaultCollection { private List list = new ArrayList(); private static CommandDataDefaultCollection instance = new CommandDataDefaultCollection(); - public static List getAllCommandsStatic() { - return instance.getCommands(); + public static List getAllCommandsStatic(boolean sorted) { + List ret = instance.getCommands(); + if (sorted) { + for (int i=0;i getDefaultCommandsStatic() { return getDefaultCommands(); } - public static List getDefaultCommandsMenuStatic() { + public static List getDefaultCommandsMenuStatic(boolean sorted) { List list = getDefaultCommandsStatic(); List ret = new ArrayList(); - for (CommandData data : list) { - ret.add(new MenuData(data)); + for (int i=0;i getCommands() { return list; } - public static List getCommandsNative(List list) { + public static List getCommandsNative(List list, boolean sorted) { if (list == null) { - list = getAllCommandsStatic(); + list = getAllCommandsStatic(false); } - return getCommandData(list, Utils.getOS()); + return getCommandData(list, Utils.getOS(), sorted); } - public static List getDefaultCommands() { - List listAll = getAllCommandsStatic(); + private static List getDefaultCommands() { + List listAll = getAllCommandsStatic(false); List listOS = new ArrayList(); List listDefault = new ArrayList(); OS os = Utils.getOS(); // now get all data by OS - listOS = getCommandData(listAll, os); + listOS = getCommandData(listAll, os, false); // now get by name switch(os) { @@ -197,11 +207,17 @@ public static List getDefaultCommands() { return listDefault; } - public static List getCommandData(List list, OS os) { + public static List getCommandData(List list, OS os, boolean sorted) { List listOut = new ArrayList(); + int position = 0; for (CommandData entry : list) { if (entry.getOS() == os) { - listOut.add(entry); + CommandData newData = new CommandData(entry); + if (sorted) { + newData.setPosition(position); + } + listOut.add(newData); + position++; } } return listOut; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsPage.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsPage.java index a5dd8793..ad84394e 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsPage.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsPage.java @@ -130,7 +130,7 @@ protected Control createContents(Composite parent) { cmdStore.load(); // get the native commands list - cmdList = CommandDataDefaultCollection.getCommandsNative(cmdStore.getAllCommands()); + cmdList = CommandDataDefaultCollection.getCommandsNative(cmdStore.getAllCommands(), true); // menu store menuStore = new MenuDataStore(Activator.getDefault().getPreferenceStore()); @@ -421,7 +421,6 @@ private void addNewDialog() { if (dialog.open() == Window.OK) { menuStore.add(data); refreshTableViewer(data); - return; } } @@ -432,7 +431,6 @@ private void addCopyDialog() { if (dialog.open() == Window.OK) { menuStore.add(data); refreshTableViewer(data); - return; } } @@ -442,7 +440,6 @@ private void editDialog() { MenuDataDialog dialog = new MenuDataDialog(getShell(), data, cmdStore, cmdList, true); if (dialog.open() == Window.OK) { refreshTableViewer(data); - return; } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java index 3ce6c9c5..76f668e5 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java @@ -21,8 +21,8 @@ public class Initializer extends AbstractPreferenceInitializer { public void initializeDefaultPreferences() { IPreferenceStore store = Activator.getDefault().getPreferenceStore(); - String defaultCommand = PreferenceValueConverter.asCommandDataString(CommandDataDefaultCollection.getAllCommandsStatic()); - String defaultMenu = PreferenceValueConverter.asCommandMenuDataString(CommandDataDefaultCollection.getDefaultCommandsMenuStatic()); + String defaultCommand = PreferenceValueConverter.asCommandDataString(CommandDataDefaultCollection.getCommandsNative(null, true)); + String defaultMenu = PreferenceValueConverter.asCommandMenuDataString(CommandDataDefaultCollection.getDefaultCommandsMenuStatic(true)); store.setDefault(Constants.PREF_COMMANDS, defaultCommand); store.setDefault(Constants.PREF_MENU, defaultMenu); //getDefaultPresets(); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java index 1b6b79b7..05e88d81 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java @@ -85,16 +85,16 @@ public boolean deserialize(String value, StringTokenizer tokenizer, String delim // set members setPosition(Integer.parseInt(tokenizer.nextToken())); setEnabled(Boolean.valueOf(tokenizer.nextToken()).booleanValue()); - setId(tokenizer.nextToken()); + //setId(tokenizer.nextToken()); setName(tokenizer.nextToken()); - // + // command data setCommandData(new CommandData(), false); getCommandData().deserialize(null, tokenizer, delimiter); return true; } public String serialize(String delimiter) { - return Integer.toString(getPosition()) + delimiter + Boolean.toString(isEnabled())+ delimiter + getId() + delimiter + getName() + delimiter + commandData.serialize(delimiter); + return Integer.toString(getPosition()) + delimiter + Boolean.toString(isEnabled())+ delimiter + /*getId() + delimiter +*/ getName() + delimiter + commandData.serialize(delimiter); } public void setPosition(int position) { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataContentProvider.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataContentProvider.java index 9fe95b26..071d46e8 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataContentProvider.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataContentProvider.java @@ -16,20 +16,14 @@ public class MenuDataContentProvider implements IStructuredContentProvider { - private MenuDataStore store; - public Object[] getElements(Object inputElement) { - return store.getCommandMenuDataArray(); + return ((MenuDataStore)inputElement).getCommandMenuDataArray(); } public void dispose() { - store = null; } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - if(newInput instanceof MenuDataStore) { - store = (MenuDataStore)newInput; - } } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java index 05c7486c..30ebad23 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java @@ -43,7 +43,7 @@ public MenuData[] getCommandMenuDataArray() { } MenuData[] allArray = new MenuData[allItems.size()]; for(int i = 0 ; i < allArray.length ; i++) { - allArray[i] = (MenuData)allItems.get(i); + allArray[i] = allItems.get(i); } return allArray; } From 7f2ad8b5fe284e67bd472577c564bf64c1507041 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Wed, 13 Jul 2016 22:28:15 +0200 Subject: [PATCH 11/73] fixed sorting of native commands for menu reference Signed-off-by: Andre Bossert --- .../preferences/CommandDataDefaultCollection.java | 10 +++------- .../easyshell/plugin/preferences/Initializer.java | 2 +- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java index 62f1388f..c869d703 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java @@ -36,12 +36,8 @@ public static List getAllCommandsStatic(boolean sorted) { return ret; } - public static List getDefaultCommandsStatic() { - return getDefaultCommands(); - } - - public static List getDefaultCommandsMenuStatic(boolean sorted) { - List list = getDefaultCommandsStatic(); + public static List getCommandsNativeAsMenu(boolean sorted) { + List list = getDefaultCommands(); List ret = new ArrayList(); for (int i=0;i getDefaultCommands() { List listDefault = new ArrayList(); OS os = Utils.getOS(); // now get all data by OS - listOS = getCommandData(listAll, os, false); + listOS = getCommandData(listAll, os, true); // now get by name switch(os) { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java index 76f668e5..8da4fe1a 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java @@ -22,7 +22,7 @@ public class Initializer extends AbstractPreferenceInitializer { public void initializeDefaultPreferences() { IPreferenceStore store = Activator.getDefault().getPreferenceStore(); String defaultCommand = PreferenceValueConverter.asCommandDataString(CommandDataDefaultCollection.getCommandsNative(null, true)); - String defaultMenu = PreferenceValueConverter.asCommandMenuDataString(CommandDataDefaultCollection.getDefaultCommandsMenuStatic(true)); + String defaultMenu = PreferenceValueConverter.asCommandMenuDataString(CommandDataDefaultCollection.getCommandsNativeAsMenu(true)); store.setDefault(Constants.PREF_COMMANDS, defaultCommand); store.setDefault(Constants.PREF_MENU, defaultMenu); //getDefaultPresets(); From 34e7cfee9a1d25c0fc127e889a1e3dcc3bbbc67e Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Wed, 13 Jul 2016 22:32:34 +0200 Subject: [PATCH 12/73] renaming of ResourceType members Signed-off-by: Andre Bossert --- .../plugin/preferences/CommandData.java | 2 +- .../CommandDataDefaultCollection.java | 62 +++++++++---------- .../plugin/preferences/MenuDataDialog.java | 2 +- .../easyshell/plugin/types/ResourceType.java | 2 +- 4 files changed, 34 insertions(+), 34 deletions(-) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java index d5c8ec5f..ae58a664 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java @@ -28,7 +28,7 @@ public class CommandData { private PresetType presetType = PresetType.presetUser; private OS os = OS.osUnknown; private String name = "MyNewCommand"; - private ResourceType resType = ResourceType.resourceFileOrFolder; + private ResourceType resType = ResourceType.resourceTypeFileOrDirectory; private CommandType cmdType = CommandType.commandTypeOther; private String command = "my_new_command"; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java index c869d703..da748fb0 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java @@ -51,87 +51,87 @@ public static List getCommandsNativeAsMenu(boolean sorted) { CommandDataDefaultCollection() { // Windows DOS-Shell - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "DOS-Shell", ResourceType.resourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "DOS-Shell", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} cmd.exe /K")); - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "DOS-Shell", ResourceType.resourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "DOS-Shell", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} ${easyshell:resource_name}")); // Windows Explorer - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Explorer", ResourceType.resourceFileOrFolder, CommandType.commandTypeExplore, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Explorer", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, "explorer.exe /select, ${easyshell:resource_loc}")); // Windows PowerShell - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "PowerShell", ResourceType.resourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "PowerShell", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} powershell.exe")); - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "PowerShell", ResourceType.resourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "PowerShell", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} powershell.exe -command ./''${easyshell:resource_name}''")); // Windows Cygwin (Bash) - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Cygwin\\bin\\bash.exe\"")); - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Cygwin\\bin\\bash.exe\" -c ./''${easyshell:resource_name}''")); // Windows Console - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Console", ResourceType.resourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Console", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, "console.exe -w \"${easyshell:project_name}\" -d ${easyshell:container_loc}")); - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, "console.exe -w \"${easyshell:project_name}\" -d ${easyshell:container_loc} -r \"/k\\\"${easyshell:resource_name}\\\"\"")); // Windows Git-Bash - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Git-Bash", ResourceType.resourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Git-Bash", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Program Files (x86)\\Git\\bin\\bash.exe\" --login -i")); - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Program Files (x86)\\Git\\bin\\bash.exe\" --login -i -c ./''${easyshell:resource_name}''")); // Windows ConEmu - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "ConEmu", ResourceType.resourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "ConEmu", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, "ConEmu.exe /Title \"${easyshell:project_name}\" /Dir \"${easyshell:container_loc}\" /Single /cmd cmd")); - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, "ConEmu.exe /Title \"${easyshell:project_name}\" /Dir \"${easyshell:container_loc}\" /Single /cmd \"${easyshell:resource_name}\"")); // Windows TotalCommander - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "TotalCommander", ResourceType.resourceFileOrFolder, CommandType.commandTypeExplore, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "TotalCommander", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, "totalcmd.exe /O /T ${easyshell:container_loc}")); // Windows Clipboard - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Full path", ResourceType.resourceFileOrFolder, CommandType.commandTypeClipboard, + list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Full path", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeClipboard, "\"${easyshell:resource_loc}\"${easyshell:line_separator}")); // Linux KDE Konsole - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "KDE Konsole", ResourceType.resourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "KDE Konsole", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, "konsole --workdir ${easyshell:container_loc}")); - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "KDE Konsole", ResourceType.resourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "KDE Konsole", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, "konsole --workdir ${easyshell:container_loc} --noclose -e ${easyshell:resource_loc}")); // Linux Konqueror - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Konqueror", ResourceType.resourceFileOrFolder, CommandType.commandTypeExplore, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Konqueror", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, "konqueror file:\"${easyshell:resource_loc}\"")); // Linux Gnome Terminal - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Gnome Terminal", ResourceType.resourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Gnome Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, "gnome-terminal --working-directory=${easyshell:container_loc}")); - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Gnome Terminal", ResourceType.resourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Gnome Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, "gnome-terminal --working-directory=${easyshell:container_loc} --command=./''${easyshell:resource_name}''")); // Linux Xfce Terminal - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Xfce Terminal", ResourceType.resourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Xfce Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, "xfce4-terminal --working-directory=${easyshell:container_loc}")); - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Xfce Terminal", ResourceType.resourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Xfce Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, "xfce4-terminal --working-directory=${easyshell:container_loc} --command=./''${easyshell:resource_name}'' --hold")); // Linux Nautilus - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Nautilus", ResourceType.resourceFileOrFolder, CommandType.commandTypeExplore, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Nautilus", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, "nautilus ${easyshell:resource_loc}")); // Linux Dolphin - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Dolphin", ResourceType.resourceFileOrFolder, CommandType.commandTypeExplore, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Dolphin", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, "dolphin --select ${easyshell:resource_loc}")); // Linux Nemo - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Nemo", ResourceType.resourceFileOrFolder, CommandType.commandTypeExplore, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Nemo", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, "nemo ${easyshell:resource_loc}")); // Linux Thunar - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Thunar", ResourceType.resourceFileOrFolder, CommandType.commandTypeExplore, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Thunar", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, "thunar ${easyshell:resource_loc}")); // Linux Clipboard - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Full path", ResourceType.resourceFileOrFolder, CommandType.commandTypeClipboard, + list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Full path", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeClipboard, "${easyshell:resource_loc}${easyshell:line_separator}")); // MAC OS X Terminal - list.add(new CommandData(PresetType.presetPlugin, OS.osMacOSX, "Terminal", ResourceType.resourceFileOrFolder, CommandType.commandTypeOpen, + list.add(new CommandData(PresetType.presetPlugin, OS.osMacOSX, "Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, "open -a Terminal ${easyshell:container_loc}")); - list.add(new CommandData(PresetType.presetPlugin, OS.osMacOSX, "Terminal", ResourceType.resourceFileOrFolder, CommandType.commandTypeRun, + list.add(new CommandData(PresetType.presetPlugin, OS.osMacOSX, "Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, "open -a Terminal ${easyshell:container_loc}")); // MAC OS X Finder - list.add(new CommandData(PresetType.presetPlugin, OS.osMacOSX, "Finder", ResourceType.resourceFileOrFolder, CommandType.commandTypeExplore, + list.add(new CommandData(PresetType.presetPlugin, OS.osMacOSX, "Finder", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, "open -R ${easyshell:resource_loc}")); // MAC OS X Clipboard - list.add(new CommandData(PresetType.presetPlugin, OS.osMacOSX, "Full path", ResourceType.resourceFileOrFolder, CommandType.commandTypeClipboard, + list.add(new CommandData(PresetType.presetPlugin, OS.osMacOSX, "Full path", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeClipboard, "${easyshell:resource_loc}${easyshell:line_separator}")); } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java index 9ef54ce0..2f342832 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java @@ -218,7 +218,7 @@ private void removeCommand(int index, CommandData data) { } private void addNewDialog() { - CommandData data = new CommandData(PresetType.presetUser, Utils.getOS(), "MyNewCommand", ResourceType.resourceFileOrFolder, CommandType.commandTypeOther, "my_new_command"); + CommandData data = new CommandData(PresetType.presetUser, Utils.getOS(), "MyNewCommand", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOther, "my_new_command"); addDialog(data); } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/ResourceType.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/ResourceType.java index 559af676..538e1580 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/ResourceType.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/ResourceType.java @@ -18,7 +18,7 @@ public enum ResourceType { resourceTypeUnknown(-1, "Unknown"), resourceTypeFile(0, "File"), resourceTypeFolder(1, "Folder"), - resourceFileOrFolder(2, "File or Folder"); + resourceTypeFileOrDirectory(2, "File or Directory"); // attributes private final int id; private final String name; From 53dc3d6d67c6a6908649a03ad7cd0bcdb678de63 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Thu, 14 Jul 2016 13:15:05 +0200 Subject: [PATCH 13/73] UUIDs: enabled again and fixed their handling - now sorting in the UI and identification with UUID are independent - adding, copying and deleting are working as expected now - added generated UUIDs in file uuids.txt -> to be used for default entries Signed-off-by: Andre Bossert --- .../plugin/preferences/CommandData.java | 43 ++++--- .../CommandDataDefaultCollection.java | 80 +++++++------ .../plugin/preferences/CommandsPage.java | 4 +- .../plugin/preferences/MenuData.java | 52 +++++--- .../plugin/preferences/MenuDataDialog.java | 4 +- uuids.txt | 111 ++++++++++++++++++ 6 files changed, 225 insertions(+), 69 deletions(-) create mode 100644 uuids.txt diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java index ae58a664..8223474c 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java @@ -23,16 +23,21 @@ public class CommandData { // internal private int position = 0; - private String id = UUID.randomUUID().toString(); + private String id = null; // command - private PresetType presetType = PresetType.presetUser; + private PresetType presetType = PresetType.presetUnknown; private OS os = OS.osUnknown; - private String name = "MyNewCommand"; - private ResourceType resType = ResourceType.resourceTypeFileOrDirectory; - private CommandType cmdType = CommandType.commandTypeOther; - private String command = "my_new_command"; - - public CommandData(PresetType presetType, OS os, String name, ResourceType resType, CommandType cmdType, String command) { + private String name = null; + private ResourceType resType = ResourceType.resourceTypeUnknown; + private CommandType cmdType = CommandType.commandTypeUnknown; + private String command = null; + + public CommandData(String id, PresetType presetType, OS os, String name, ResourceType resType, CommandType cmdType, String command) { + if (id == null || id.isEmpty()) { + this.id = UUID.randomUUID().toString(); + } else { + this.id = id; + } this.presetType = presetType; this.os = os; this.name = name; @@ -41,7 +46,8 @@ public CommandData(PresetType presetType, OS os, String name, ResourceType resTy this.command = command; } - public CommandData(CommandData commandData) { + public CommandData(CommandData commandData, String newId) { + this.id = newId; this.presetType = commandData.getPresetType(); this.os = commandData.getOS(); this.name = commandData.getName(); @@ -50,6 +56,10 @@ public CommandData(CommandData commandData) { this.command = commandData.getCommand(); } + public CommandData(CommandData commandData, boolean generateNewId) { + this(commandData, generateNewId ? UUID.randomUUID().toString() : commandData.getId()); + } + public CommandData() { } @@ -122,14 +132,14 @@ public boolean equals(Object object) { return false; } CommandData data = (CommandData)object; - if(data.getPosition() == this.getPosition() && - data.getName().equals(this.getName()) && + if(data.getId().equals(this.getId()) + /*data.getPosition() == this.getPosition() &&*/ + /*data.getName().equals(this.getName()) && data.getOS() == this.getOS() && data.getPresetType() == this.getPresetType() && data.getResourceType() == this.getResourceType() && data.getCommandType() == this.getCommandType() && - data.getCommand().equals(this.getCommand() - ) + data.getCommand().equals(this.getCommand()*/ ) { return true; @@ -144,9 +154,10 @@ public boolean deserialize(String value, StringTokenizer tokenizer, String delim if (tokenizer == null) { tokenizer = new StringTokenizer(value,delimiter); } - // set members + // set internal members setPosition(Integer.parseInt(tokenizer.nextToken())); - //setId(tokenizer.nextToken()); + setId(tokenizer.nextToken()); + // set command data members setPresetType(PresetType.getFromEnum(tokenizer.nextToken())); setOs(OS.getFromEnum(tokenizer.nextToken())); setName(tokenizer.nextToken()); @@ -157,7 +168,7 @@ public boolean deserialize(String value, StringTokenizer tokenizer, String delim } public String serialize(String delimiter) { - return Integer.toString(getPosition()) + delimiter + /*getId() + delimiter +*/ getPresetType().toString() + delimiter + getOS().toString() + delimiter + getName() + delimiter + getResourceType().toString() + delimiter + getCommandType().toString() + delimiter + getCommand() + delimiter; + return Integer.toString(getPosition()) + delimiter + getId() + delimiter + getPresetType().toString() + delimiter + getOS().toString() + delimiter + getName() + delimiter + getResourceType().toString() + delimiter + getCommandType().toString() + delimiter + getCommand() + delimiter; } public String getTypeIcon() { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java index da748fb0..275359e1 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java @@ -40,7 +40,8 @@ public static List getCommandsNativeAsMenu(boolean sorted) { List list = getDefaultCommands(); List ret = new ArrayList(); for (int i=0;i getCommandsNativeAsMenu(boolean sorted) { } CommandDataDefaultCollection() { + addWindowsCommands(); + addLinuxCommands(); + addMacOSXCommands(); + } + + + private void addWindowsCommands() { // Windows DOS-Shell - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "DOS-Shell", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, + list.add(new CommandData("cd361a40-bb37-4fa2-9d2e-b62794294a59", PresetType.presetPlugin, OS.osWindows, "DOS-Shell", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} cmd.exe /K")); - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "DOS-Shell", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, + list.add(new CommandData("f740984b-e9d5-4ebc-b9b5-c6b8527f886c", PresetType.presetPlugin, OS.osWindows, "DOS-Shell", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} ${easyshell:resource_name}")); // Windows Explorer - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Explorer", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, + list.add(new CommandData("ae0e5b6e-0b20-4c52-9708-ba7e317d1dee", PresetType.presetPlugin, OS.osWindows, "Explorer", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, "explorer.exe /select, ${easyshell:resource_loc}")); // Windows PowerShell - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "PowerShell", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, + list.add(new CommandData("9cb0d29e-93aa-4139-93d2-079ba63ff726", PresetType.presetPlugin, OS.osWindows, "PowerShell", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} powershell.exe")); - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "PowerShell", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, + list.add(new CommandData("af2968d0-3a1a-40db-b3cb-e2e16293a285", PresetType.presetPlugin, OS.osWindows, "PowerShell", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} powershell.exe -command ./''${easyshell:resource_name}''")); // Windows Cygwin (Bash) - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, + list.add(new CommandData("5b1e3806-a9ab-4866-b660-823ac388a575", PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Cygwin\\bin\\bash.exe\"")); - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, + list.add(new CommandData("2002e587-70a3-4204-b1a5-6faf6271ad08", PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Cygwin\\bin\\bash.exe\" -c ./''${easyshell:resource_name}''")); // Windows Console - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Console", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, + list.add(new CommandData("60fd43d2-d837-41d1-aaa3-3f5cab6bf0fb", PresetType.presetPlugin, OS.osWindows, "Console", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, "console.exe -w \"${easyshell:project_name}\" -d ${easyshell:container_loc}")); - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, + list.add(new CommandData("af6d97f2-f0a8-46e2-8234-74c0ee3e6007", PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, "console.exe -w \"${easyshell:project_name}\" -d ${easyshell:container_loc} -r \"/k\\\"${easyshell:resource_name}\\\"\"")); // Windows Git-Bash - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Git-Bash", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, + list.add(new CommandData("24419204-c8e5-4d79-a7b8-b14e93077cf0", PresetType.presetPlugin, OS.osWindows, "Git-Bash", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Program Files (x86)\\Git\\bin\\bash.exe\" --login -i")); - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, + list.add(new CommandData("ee790c7f-9c6d-40f9-84f6-51a948a59d45", PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Program Files (x86)\\Git\\bin\\bash.exe\" --login -i -c ./''${easyshell:resource_name}''")); // Windows ConEmu - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "ConEmu", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, + list.add(new CommandData("1bd62e22-cd93-4136-b643-1cbb9579c195", PresetType.presetPlugin, OS.osWindows, "ConEmu", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, "ConEmu.exe /Title \"${easyshell:project_name}\" /Dir \"${easyshell:container_loc}\" /Single /cmd cmd")); - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, + list.add(new CommandData("c2b73077-ffd9-4fb7-9793-189be9f13ebb", PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, "ConEmu.exe /Title \"${easyshell:project_name}\" /Dir \"${easyshell:container_loc}\" /Single /cmd \"${easyshell:resource_name}\"")); // Windows TotalCommander - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "TotalCommander", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, + list.add(new CommandData("e487327c-dfdb-42e7-bf16-3b81a34e5703", PresetType.presetPlugin, OS.osWindows, "TotalCommander", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, "totalcmd.exe /O /T ${easyshell:container_loc}")); // Windows Clipboard - list.add(new CommandData(PresetType.presetPlugin, OS.osWindows, "Full path", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeClipboard, + list.add(new CommandData("67aa9dff-6bbb-4b47-8b43-8a82a7a279fa", PresetType.presetPlugin, OS.osWindows, "Full path", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeClipboard, "\"${easyshell:resource_loc}\"${easyshell:line_separator}")); + } + + private void addLinuxCommands() { // Linux KDE Konsole - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "KDE Konsole", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, + list.add(new CommandData("c2b1612b-9037-484a-a763-d013679bdbe7", PresetType.presetPlugin, OS.osLinux, "KDE Konsole", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, "konsole --workdir ${easyshell:container_loc}")); - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "KDE Konsole", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, + list.add(new CommandData("e634b20a-cf57-47f0-aa27-b8fc95917f35", PresetType.presetPlugin, OS.osLinux, "KDE Konsole", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, "konsole --workdir ${easyshell:container_loc} --noclose -e ${easyshell:resource_loc}")); // Linux Konqueror - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Konqueror", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, + list.add(new CommandData("8873342e-e02b-4feb-8f56-9f52524c0f46", PresetType.presetPlugin, OS.osLinux, "Konqueror", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, "konqueror file:\"${easyshell:resource_loc}\"")); // Linux Gnome Terminal - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Gnome Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, + list.add(new CommandData("53f7b6a3-f8d5-4682-b0ef-1d6ceec5cc8a", PresetType.presetPlugin, OS.osLinux, "Gnome Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, "gnome-terminal --working-directory=${easyshell:container_loc}")); - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Gnome Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, + list.add(new CommandData("c6126958-32f2-4f96-9933-69ddd956f2e9", PresetType.presetPlugin, OS.osLinux, "Gnome Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, "gnome-terminal --working-directory=${easyshell:container_loc} --command=./''${easyshell:resource_name}''")); // Linux Xfce Terminal - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Xfce Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, + list.add(new CommandData("8175f9a7-4e54-4367-a6b6-251aedc187df", PresetType.presetPlugin, OS.osLinux, "Xfce Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, "xfce4-terminal --working-directory=${easyshell:container_loc}")); - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Xfce Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, + list.add(new CommandData("adf40e10-0ee9-4abe-8282-aff7d51bb68d", PresetType.presetPlugin, OS.osLinux, "Xfce Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, "xfce4-terminal --working-directory=${easyshell:container_loc} --command=./''${easyshell:resource_name}'' --hold")); // Linux Nautilus - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Nautilus", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, + list.add(new CommandData("1747b189-ed7f-4546-8c98-f99a3c1fb13b", PresetType.presetPlugin, OS.osLinux, "Nautilus", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, "nautilus ${easyshell:resource_loc}")); // Linux Dolphin - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Dolphin", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, + list.add(new CommandData("4fbfa632-5455-4384-9f9e-773603a12bea", PresetType.presetPlugin, OS.osLinux, "Dolphin", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, "dolphin --select ${easyshell:resource_loc}")); // Linux Nemo - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Nemo", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, + list.add(new CommandData("8e14d26d-2981-4b81-b8e5-6a942c6f2c59", PresetType.presetPlugin, OS.osLinux, "Nemo", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, "nemo ${easyshell:resource_loc}")); // Linux Thunar - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Thunar", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, + list.add(new CommandData("cf8d4d60-10f4-4a31-a423-676d02d974e0", PresetType.presetPlugin, OS.osLinux, "Thunar", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, "thunar ${easyshell:resource_loc}")); // Linux Clipboard - list.add(new CommandData(PresetType.presetPlugin, OS.osLinux, "Full path", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeClipboard, + list.add(new CommandData("33043fe3-1a5f-46d7-b94e-9a02ef204e7d", PresetType.presetPlugin, OS.osLinux, "Full path", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeClipboard, "${easyshell:resource_loc}${easyshell:line_separator}")); + } + + private void addMacOSXCommands() { // MAC OS X Terminal - list.add(new CommandData(PresetType.presetPlugin, OS.osMacOSX, "Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, + list.add(new CommandData("e6918fe0-38b8-450b-a4be-d9eecc0dc0b4", PresetType.presetPlugin, OS.osMacOSX, "Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, "open -a Terminal ${easyshell:container_loc}")); - list.add(new CommandData(PresetType.presetPlugin, OS.osMacOSX, "Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, + list.add(new CommandData("db61d61e-8bf4-41d0-a1d8-00379e4d1db1", PresetType.presetPlugin, OS.osMacOSX, "Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, "open -a Terminal ${easyshell:container_loc}")); // MAC OS X Finder - list.add(new CommandData(PresetType.presetPlugin, OS.osMacOSX, "Finder", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, + list.add(new CommandData("f6bcdd71-4687-46d8-bf34-2780bafd762a", PresetType.presetPlugin, OS.osMacOSX, "Finder", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, "open -R ${easyshell:resource_loc}")); // MAC OS X Clipboard - list.add(new CommandData(PresetType.presetPlugin, OS.osMacOSX, "Full path", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeClipboard, + list.add(new CommandData("cd32fa5a-34d7-4551-8bd0-3aae0dc444d0", PresetType.presetPlugin, OS.osMacOSX, "Full path", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeClipboard, "${easyshell:resource_loc}${easyshell:line_separator}")); } @@ -208,7 +222,7 @@ public static List getCommandData(List list, OS os, bo int position = 0; for (CommandData entry : list) { if (entry.getOS() == os) { - CommandData newData = new CommandData(entry); + CommandData newData = new CommandData(entry, false); if (sorted) { newData.setPosition(position); } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsPage.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsPage.java index ad84394e..34c9582e 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsPage.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsPage.java @@ -416,7 +416,7 @@ public void controlResized(ControlEvent e) { } private void addNewDialog() { - MenuData data = new MenuData(cmdList.get(0)); + MenuData data = new MenuData(cmdList.get(0), true, true); MenuDataDialog dialog = new MenuDataDialog(getShell(), data, cmdStore, cmdList, false); if (dialog.open() == Window.OK) { menuStore.add(data); @@ -426,7 +426,7 @@ private void addNewDialog() { private void addCopyDialog() { IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection(); - MenuData data = new MenuData((MenuData)selection.getFirstElement()); + MenuData data = new MenuData((MenuData)selection.getFirstElement(), true); MenuDataDialog dialog = new MenuDataDialog(getShell(), data, cmdStore, cmdList, false); if (dialog.open() == Window.OK) { menuStore.add(data); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java index 05e88d81..8b92f582 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java @@ -16,27 +16,45 @@ public class MenuData { - // status + // internal private int position = 0; - private boolean enabled = true; + private String id = null; // menu - private String id = UUID.randomUUID().toString(); + private boolean enabled = true; private String name = null; + // copy of or reference to command + private CommandData commandData = null; + + public MenuData(String id, boolean enabled, String name, CommandData commandData, boolean setDefaultName) { + if (id == null || id.isEmpty()) { + this.id = UUID.randomUUID().toString(); + } else { + this.id = id; + } + this.enabled = enabled; + this.name = name; + setCommandData(commandData, setDefaultName); + } - // command data - private CommandData commandData; + public MenuData(String newId, CommandData commandData, boolean setDefaultName) { + this.id = newId; + setCommandData(commandData, setDefaultName); + } - public MenuData(CommandData commandData) { - this.commandData = commandData; - setDefaultName(); + public MenuData(CommandData commandData, boolean setDefaultName, boolean generateNewId) { + this(generateNewId ? UUID.randomUUID().toString() : commandData.getId(), commandData, setDefaultName); } - public MenuData(MenuData data) { - this(data.getCommandData()); + public MenuData(String newId, MenuData data) { + this(newId, data.getCommandData(), false); this.name = data.getName(); } + public MenuData(MenuData data, boolean generateNewId) { + this(generateNewId ? UUID.randomUUID().toString() : data.getId(), data); + } + public MenuData() { } @@ -65,9 +83,10 @@ public boolean equals(Object object) { return false; } MenuData data = (MenuData)object; - if( data.getPosition() == this.getPosition() && + if( data.getId().equals(this.getId()) + /*data.getPosition() == this.getPosition() && data.getName().equals(this.getName()) && - data.getCommandData().equals(this.getCommandData()) + data.getCommandData().equals(this.getCommandData())*/ ) { return true; @@ -82,19 +101,20 @@ public boolean deserialize(String value, StringTokenizer tokenizer, String delim if (tokenizer == null) { tokenizer = new StringTokenizer(value,delimiter); } - // set members + // set internal members setPosition(Integer.parseInt(tokenizer.nextToken())); + setId(tokenizer.nextToken()); + // set menu data members setEnabled(Boolean.valueOf(tokenizer.nextToken()).booleanValue()); - //setId(tokenizer.nextToken()); setName(tokenizer.nextToken()); - // command data + // set command data members setCommandData(new CommandData(), false); getCommandData().deserialize(null, tokenizer, delimiter); return true; } public String serialize(String delimiter) { - return Integer.toString(getPosition()) + delimiter + Boolean.toString(isEnabled())+ delimiter + /*getId() + delimiter +*/ getName() + delimiter + commandData.serialize(delimiter); + return Integer.toString(getPosition()) + delimiter + getId() + delimiter + Boolean.toString(isEnabled())+ delimiter + getName() + delimiter + commandData.serialize(delimiter); } public void setPosition(int position) { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java index 2f342832..772611d0 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java @@ -218,13 +218,13 @@ private void removeCommand(int index, CommandData data) { } private void addNewDialog() { - CommandData data = new CommandData(PresetType.presetUser, Utils.getOS(), "MyNewCommand", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOther, "my_new_command"); + CommandData data = new CommandData(null, PresetType.presetUser, Utils.getOS(), "MyNewCommand", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOther, "my_new_command"); addDialog(data); } private void addCopyDialog() { int index = commandCombo.getSelectionIndex(); - CommandData data = new CommandData(cmdList.get(index)); + CommandData data = new CommandData(cmdList.get(index), true); data.setPresetType(PresetType.presetUser); addDialog(data); } diff --git a/uuids.txt b/uuids.txt new file mode 100644 index 00000000..0e2dc7e7 --- /dev/null +++ b/uuids.txt @@ -0,0 +1,111 @@ +UUIDs V4 generated by https://www.uuidgenerator.net/ + +EasyShell Defaults 2.0 + +Windows +cd361a40-bb37-4fa2-9d2e-b62794294a59 +f740984b-e9d5-4ebc-b9b5-c6b8527f886c +ae0e5b6e-0b20-4c52-9708-ba7e317d1dee +9cb0d29e-93aa-4139-93d2-079ba63ff726 +af2968d0-3a1a-40db-b3cb-e2e16293a285 +5b1e3806-a9ab-4866-b660-823ac388a575 +2002e587-70a3-4204-b1a5-6faf6271ad08 +60fd43d2-d837-41d1-aaa3-3f5cab6bf0fb +af6d97f2-f0a8-46e2-8234-74c0ee3e6007 +24419204-c8e5-4d79-a7b8-b14e93077cf0 +ee790c7f-9c6d-40f9-84f6-51a948a59d45 +1bd62e22-cd93-4136-b643-1cbb9579c195 +c2b73077-ffd9-4fb7-9793-189be9f13ebb +e487327c-dfdb-42e7-bf16-3b81a34e5703 +67aa9dff-6bbb-4b47-8b43-8a82a7a279fa + +Linux +c2b1612b-9037-484a-a763-d013679bdbe7 +e634b20a-cf57-47f0-aa27-b8fc95917f35 +8873342e-e02b-4feb-8f56-9f52524c0f46 +53f7b6a3-f8d5-4682-b0ef-1d6ceec5cc8a +c6126958-32f2-4f96-9933-69ddd956f2e9 +8175f9a7-4e54-4367-a6b6-251aedc187df +adf40e10-0ee9-4abe-8282-aff7d51bb68d +1747b189-ed7f-4546-8c98-f99a3c1fb13b +4fbfa632-5455-4384-9f9e-773603a12bea +8e14d26d-2981-4b81-b8e5-6a942c6f2c59 +cf8d4d60-10f4-4a31-a423-676d02d974e0 +33043fe3-1a5f-46d7-b94e-9a02ef204e7d + +MacOSX +e6918fe0-38b8-450b-a4be-d9eecc0dc0b4 +db61d61e-8bf4-41d0-a1d8-00379e4d1db1 +f6bcdd71-4687-46d8-bf34-2780bafd762a +cd32fa5a-34d7-4551-8bd0-3aae0dc444d0 + +Free +e5b3b0f6-e27c-4a2d-aa1a-caef784dd3da +22ec69ee-e39e-4fa6-a241-4e950d3235af +025e2f56-3d2e-47e1-8daa-c2c74049b150 +51ed300a-35d0-4e67-a5f8-6ebd7012a564 +8e366a34-5ce2-4430-bc21-20e176e0128c +2a979af5-86a7-440e-b4f0-8442e85412e4 +cb9a8c00-89bc-453c-aeff-ae94c0d9e44a +f573a4de-22fa-467f-a433-042d0992ab28 +1cc39e61-8d8d-4493-8baa-7a11ff01c06c +88989d78-cf17-4750-91fc-6260055743ae +e6de32cc-342a-46a0-a766-ac74e7e4000d +d2726c3f-6da3-46b5-8029-1c63d0ff6bd2 +03e6678b-f67f-42ed-b65f-6b6f06ec0e8f +c57a5d9f-491a-4b21-8a8b-9941b01cc049 +95cacf98-9dfc-473f-b5d3-fe4961e66ae1 +771c0bac-cdb2-47fe-a030-6b830d366da1 +61c4fef4-470a-45b1-98df-ccf9d7d91143 +40eee8f2-b29e-490b-8612-59c2b76a704d +9a11b3eb-497c-44dd-9813-a841a32465c1 +d07df65d-ccc5-4c71-82f8-3a17e608516b +f2b970ed-ef98-4ce2-861c-20f44a471f49 +8770e3c5-cd60-4c01-b1c0-8b7754b91b27 +94b0c584-0316-4dac-bd40-2ab1a0428d32 +554d1dc7-4f26-4be9-bc2a-86d5a41ec606 +1df6da5c-5455-4372-a2ae-6b1b3f910e76 +d93cd39e-1f78-47e2-90d3-88b8c8495c61 +d13ad020-aeb8-4b48-acc6-4e09dea4913a +a6728fb1-89f3-4c3a-8ab0-5c57b6d7ee48 +3c3358b2-3541-4d13-b5bc-137ba239dae7 +837716a1-5475-42fa-b40b-6d3da56197a1 +7137aada-940a-4b03-90b2-f468d696019a +4942a4bd-536e-47f4-9e98-f893a5d40a91 +5695fab2-db44-42af-a305-720fd0828557 +d8ea14e6-f21f-417c-ba9b-3c1657e0b2ee +35a4c2ac-a6b9-42b9-8fae-aa5ae16cd785 +aac5d88b-d404-4d6b-84f9-1c8446bd7714 +84ec453c-f4b3-4610-9210-6b02cde111d4 +015a75a8-5993-46a3-8307-18bdbd94bc17 +b9ded5f2-1dcc-40e5-be01-990b64a21e93 +2e2fc87e-d513-4864-8124-e6a12675445e +d7602663-d0b6-472f-a8e7-f80224142615 +ebd16ef0-0b5d-41d9-87d6-53081a534ebd +45f55881-f931-45eb-b050-6fd6bf33108c +9dea18e6-6fd2-4445-84ef-db6d23d107c3 +6ae09ecc-04b5-4c4e-a9e5-a2a787208eb1 +3484a83d-7988-497d-b068-cc96e74717b1 +213e0ae1-d548-4362-bb97-9b27e615d939 +939ff127-1b7d-4528-8d40-bd9607f5b3d2 +b3f7360a-6a37-4eb9-9b70-9387caffe969 +1cb91d59-02b7-4245-b783-fd963d597c47 +53455bec-58b3-4d21-ab6f-bdfb4fb1a950 +4d7c100b-3918-4fc9-9f39-9c3d188abd0b +2cfc91d5-4449-46ed-bc6e-0e2ea300aadb +a9eb9cc0-948b-4ca7-b86c-ad5116396c3f +7f8492a5-3423-4ffe-9e4c-0aa76319475a +fdf63c8c-f6c1-4392-8f09-c3bdef6ffe34 +48722b08-dc70-4059-915b-a3454a75eca9 +5ca27361-092a-4955-b8b4-0db7b6d6f1ba +0494f4e4-d0ea-4700-86eb-ea9ac58cb74f +fefa90d8-3b72-4313-bc48-e743ca5d903e +6e08abbc-d9ee-407a-a7ad-5e14dafc0fa2 +22da92a3-05df-4179-b9a5-3b75131a4e0b +4bfb0295-476e-4503-af55-e9eb89eb72ab +ce55f175-74a3-447d-9bba-9b24aeaa2b0d +fe0192d8-e884-4463-bc93-2746f44be0a3 +6c528020-02c1-4245-9eab-60dff12f89b0 +f01bbb14-70ae-4b24-a112-73a71496c6b8 +a2a9c831-bb20-42db-bbe1-c71b6b5019c7 +ee2db486-4df3-42c1-b19e-03761ffac105 From e22405510d456551a233aaa94c907acb23fad4e0 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Mon, 18 Jul 2016 14:38:27 +0200 Subject: [PATCH 14/73] add versioning to preference handling Signed-off-by: Andre Bossert --- .../eclipse/easyshell/plugin/Activator.java | 24 ++++++++++++++++++- .../eclipse/easyshell/plugin/Constants.java | 6 ++++- .../plugin/preferences/Initializer.java | 23 ++++++++++++------ 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java index 394bbdb1..74ad2f29 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java @@ -21,9 +21,12 @@ import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.resource.ImageRegistry; import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.eclipse.ui.preferences.ScopedPreferenceStore; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; @@ -36,12 +39,17 @@ */ public class Activator extends AbstractUIPlugin { - // The shared instance + // The shared instance private static Activator plugin; //Resource bundle. private ResourceBundle resourceBundle; + /** + * Storage for preferences. + */ + private IPreferenceStore myPreferenceStore; + /** * The constructor */ @@ -213,4 +221,18 @@ public static void logDebug(String string) { } } + @Override + public IPreferenceStore getPreferenceStore() { + // Create the preference store lazily. + if (myPreferenceStore == null) { + myPreferenceStore = getNewPreferenceStoreByVersion(Constants.PREF_VERSIONS[0]); + } + return myPreferenceStore; + } + + public IPreferenceStore getNewPreferenceStoreByVersion(String version) { + String pluginNodeName = getBundle().getSymbolicName(); + return new ScopedPreferenceStore(InstanceScope.INSTANCE, pluginNodeName + "/" + version, pluginNodeName); + } + } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/Constants.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/Constants.java index 64a00423..41fb5b40 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/Constants.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/Constants.java @@ -16,7 +16,7 @@ public interface Constants { // Plugin public static final String PLUGIN_ID = "de.anbos.eclipse.easyshell.plugin"; - // Images + // Images public static final String IMAGE_PATH = "icons/"; public static final String IMAGE_UNKNOWN = "sample.gif"; public static final String IMAGE_OPEN = "prompt.gif"; @@ -26,6 +26,10 @@ public interface Constants { public static final String IMAGE_OTHER = "editor.gif"; // Preferences + // version with index = 0 is the used one + public static final String[] PREF_VERSIONS = { + "v2_0_001" + }; public static final String PREF_COMMANDS = "COMMANDS"; public static final String PREF_MENU = "MENU"; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java index 8da4fe1a..943a4931 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java @@ -12,7 +12,11 @@ package de.anbos.eclipse.easyshell.plugin.preferences; import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; +//import org.eclipse.core.runtime.preferences.IEclipsePreferences; +//import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.jface.preference.IPreferenceStore; +//import org.osgi.service.prefs.BackingStoreException; +//import org.osgi.service.prefs.Preferences; import de.anbos.eclipse.easyshell.plugin.Activator; import de.anbos.eclipse.easyshell.plugin.Constants; @@ -20,18 +24,23 @@ public class Initializer extends AbstractPreferenceInitializer { public void initializeDefaultPreferences() { + // get the actual preference store IPreferenceStore store = Activator.getDefault().getPreferenceStore(); + /* + IEclipsePreferences instanceNode = InstanceScope.INSTANCE.getNode(Activator.PLUGIN_ID); + Preferences preferences = instanceNode.node(Constants.PREF_VERSIONS[0]); + preferences.put("test", "value"); + try { + preferences.flush(); + } catch (BackingStoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + */ String defaultCommand = PreferenceValueConverter.asCommandDataString(CommandDataDefaultCollection.getCommandsNative(null, true)); String defaultMenu = PreferenceValueConverter.asCommandMenuDataString(CommandDataDefaultCollection.getCommandsNativeAsMenu(true)); store.setDefault(Constants.PREF_COMMANDS, defaultCommand); store.setDefault(Constants.PREF_MENU, defaultMenu); - //getDefaultPresets(); - /* - store.setDefault(PreferenceConstants.P_BOOLEAN, true); - store.setDefault(PreferenceConstants.P_CHOICE, "choice2"); - store.setDefault(PreferenceConstants.P_STRING, - "Default value"); - */ } } From a361550081bfc7e48e67a4f825696342371ca991 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Tue, 19 Jul 2016 08:31:21 +0200 Subject: [PATCH 15/73] issue #53 - [v2.0] implement generic menu definition fixed: issues described in #52 - [v2.0] issues found in beta 1 - Opening the edition window for an existing entry changes its name back to the original one. - Adding a new entry sometimes changes the name of the other existing entries back to their original one. - I wouldn't automatically prefix the "menu name" with the "type" when exiting the "Edit existing command". fixed: other - menu data is changed also in case of cancel - issue #56 - [v2.0] migration support from older EasyShell v2.x (also beta releases) added: - MenuTypeName: predefined and user defined name patterns (#53) - implemented migration of store Signed-off-by: Andre Bossert --- .../eclipse/easyshell/plugin/Activator.java | 8 +- .../eclipse/easyshell/plugin/Constants.java | 13 +- .../easyshell/plugin/UIMessages.properties | 21 ++- .../plugin/commands/DefineCommands.java | 2 +- .../plugin/preferences/CommandData.java | 4 + .../CommandDataDefaultCollection.java | 2 +- .../plugin/preferences/CommandDataStore.java | 55 +++++-- .../plugin/preferences/CommandsPage.java | 73 ++++++--- .../plugin/preferences/Initializer.java | 119 +++++++++++++-- .../plugin/preferences/MenuData.java | 100 +++++++++--- .../plugin/preferences/MenuDataDialog.java | 143 ++++++++++++++---- .../preferences/MenuDataLabelProvider.java | 2 +- .../plugin/preferences/MenuDataStore.java | 18 ++- .../preferences/PreferenceValueConverter.java | 63 +++++++- .../easyshell/plugin/types/MenuNameType.java | 125 +++++++++++++++ 15 files changed, 635 insertions(+), 113 deletions(-) create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/types/MenuNameType.java diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java index 74ad2f29..76cf6d3f 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java @@ -152,28 +152,28 @@ public static void log(String title, String msg, Exception e) { public static void logSuccess(String title, String msg, Exception e, boolean tooltip) { log(Status.OK, title != null ? title + ": " + msg : msg, e); if (tooltip) { - tooltipSuccess(getResourceString("easyshell.plugin.name") + ": " + title, msg); + tooltipSuccess(title, msg); } } public static void logInfo(String title, String msg, Exception e, boolean tooltip) { log(Status.INFO, title != null ? title + ": " + msg : msg, e); if (tooltip) { - tooltipInfo(getResourceString("easyshell.plugin.name") + ": " + title, msg); + tooltipInfo(title, msg); } } public static void logWarning(String title, String msg, Exception e, boolean tooltip) { log(Status.WARNING, title != null ? title + ": " + msg : msg, e); if (tooltip) { - tooltipWarning(getResourceString("easyshell.plugin.name") + ": " + title, msg); + tooltipWarning(title, msg); } } public static void logError(String title, String msg, Exception e, boolean tooltip) { log(Status.ERROR, title != null ? title + ": " + msg : msg, e); if (tooltip) { - tooltipError(getResourceString("easyshell.plugin.name") + ": " + title, msg); + tooltipError(title, msg); } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/Constants.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/Constants.java index 41fb5b40..a1fa0ebe 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/Constants.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/Constants.java @@ -26,12 +26,17 @@ public interface Constants { public static final String IMAGE_OTHER = "editor.gif"; // Preferences - // version with index = 0 is the used one + // version with index = 0 is the actual one + // do not delete old entries !!! public static final String[] PREF_VERSIONS = { - "v2_0_001" + "v2_0_002", + "v2_0_001", + "v1_4" }; - public static final String PREF_COMMANDS = "COMMANDS"; - public static final String PREF_MENU = "MENU"; + public static final String PREF_COMMANDS_PRESET = "COMMANDS_PRESET"; + public static final String PREF_COMMANDS = "COMMANDS"; + public static final String PREF_MENU = "MENU"; + public static final String PREF_MIGRATED = "MIGRATED"; // Actions public static final String ACTION_UNKNOWN = "de.anbos.eclipse.easyshell.plugin.commands.Unknown"; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties index eda57a1a..015753b5 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties @@ -8,6 +8,12 @@ easyshell.message.error.internal=Unable to open shell easyshell.message.error.execution=Execution error easyshell.message.error.validation=Validation error +easyshell.message.warning.migrated.yes=Migrated settings from previous version "{0}".\n\nPlease verify your settings! +easyshell.message.warning.migrated.no=NOT migrated settings from previous version "{0}".\n\nPlease verify applied default settings! +easyshell.message.warning.migrated.cancel=Migration was canceled and will be executed again during next Eclipse startup.\n\nTemporary applied default settings! +easyshell.message.warning.migrated.default=First startup!\n\nPlease verify applied default settings! +easyshell.question.migrate=Do you want to migrate your settings from previous version "{0}" ? + easyshell.page.table.header.title.column0=Name easyshell.page.table.header.title.column1=Command easyshell.page.table.button.text.new=Add... @@ -24,15 +30,22 @@ easyshell.page.table.button.text.down=Down easyshell.page.table.button.tooltip.down=Move selected menu down easyshell.page.table.dialog.remove.title=Remove menu(s) easyshell.page.table.dialog.remove.question=Do you really want to remove selected menu(s) ? +easyshell.page.table.dialog.defaults.title=Restore defaults +easyshell.page.table.dialog.defaults.question=All your menu definitions will be overwritten!\n\nYou can still use "Cancel" button afterwards for undo.\n\nDo you really want to restore default settings? +easyshell.page.table.dialog.migration.title=Migration +easyshell.page.table.dialog.migration.question=You have canceled the migration of settings from previous version.\n\nAll your menu definitions will be written now and migration will be skipped completely!\n\nDo you really want to overwrite the migrated settings? easyshell.menu.editor.dialog.title.new=Create new menu easyshell.menu.editor.dialog.title.edit=Edit existing menu easyshell.menu.editor.dialog.title.group1=Menu definition +easyshell.menu.editor.dialog.title.group2=Command definition easyshell.menu.editor.dialog.error.text.name=Please enter a valid name easyshell.menu.editor.dialog.error.type.text=Please choose a valid type easyshell.menu.editor.dialog.label.active=enabled: -easyshell.menu.editor.dialog.label.name=menu name: -easyshell.menu.editor.dialog.label.combo=preset: +easyshell.menu.editor.dialog.label.name=name: +easyshell.menu.editor.dialog.label.pattern= +easyshell.menu.editor.dialog.label.combo.preset=select: +easyshell.menu.editor.dialog.label.combo.pattern=name pattern: easyshell.menu.editor.dialog.label.command=command: easyshell.menu.editor.dialog.button.text.new=New... easyshell.menu.editor.dialog.button.tooltip.new=Add new user command @@ -43,11 +56,11 @@ easyshell.menu.editor.dialog.button.tooltip.edit=Edit selected user command easyshell.menu.editor.dialog.button.text.remove=Remove... easyshell.menu.editor.dialog.button.tooltip.remove=Remove selected user command easyshell.menu.editor.dialog.title.remove=Remove user command -easyshell.menu.editor.dialog.question.remove=Do you really want to remove user command "{0}" ? +easyshell.menu.editor.dialog.question.remove=Do you really want to remove user command\n"{0}" ? easyshell.command.editor.dialog.title.new=Create new command easyshell.command.editor.dialog.title.edit=Edit existing command -easyshell.command.editor.dialog.title.group1=Command definition +easyshell.command.editor.dialog.title.group1=Command easyshell.command.editor.dialog.tooltip.group1=Add your command here easyshell.command.editor.dialog.title.group2=Usable variables easyshell.command.editor.dialog.tooltip.group2=Double click at variable copies it to clipboard diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java index 82f7f442..7c6e33af 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java @@ -41,7 +41,7 @@ public void createContributionItems(IServiceLocator serviceLocator, List items = store.getEnabledCommandMenuDataList(); for (MenuData item : items) { addItem(serviceLocator, additions, - item.getName(), + item.getNameExpanded(), "de.anbos.eclipse.easyshell.plugin.commands.execute", "de.anbos.eclipse.easyshell.plugin.commands.parameter.type", item.getCommandData().getTypeAction(), diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java index 8223474c..509abc0e 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java @@ -167,6 +167,10 @@ public boolean deserialize(String value, StringTokenizer tokenizer, String delim return true; } + public boolean deserialize_v2_0_001(String value, StringTokenizer tokenizer, String delimiter) { + return deserialize(value, tokenizer, delimiter); + } + public String serialize(String delimiter) { return Integer.toString(getPosition()) + delimiter + getId() + delimiter + getPresetType().toString() + delimiter + getOS().toString() + delimiter + getName() + delimiter + getResourceType().toString() + delimiter + getCommandType().toString() + delimiter + getCommand() + delimiter; } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java index 275359e1..669670d9 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java @@ -41,7 +41,7 @@ public static List getCommandsNativeAsMenu(boolean sorted) { List ret = new ArrayList(); for (int i=0;i getAllCommands() { - return items; + return items; + } + + private List getUserCommands() { + List userItems = new ArrayList(); + for (CommandData data : items) { + if (data.getPresetType() == PresetType.presetUser) { + userItems.add(data); + } + } + return userItems; + } + + private List getPresetCommands() { + List presetItems = new ArrayList(); + for (CommandData data : items) { + if (data.getPresetType() == PresetType.presetPlugin) { + presetItems.add(data); + } + } + return presetItems; } public CommandData[] getAllCommandsArray() { @@ -48,7 +69,7 @@ public CommandData[] getAllCommandsArray() { } public CommandData getPreviousElement(CommandData data) { - sort(); + sort(items); for(int i = 0 ; i < items.size() ; i++) { CommandData item = (CommandData)items.get(i); if(item.equals(data)) { @@ -63,7 +84,7 @@ public CommandData getPreviousElement(CommandData data) { } public CommandData getNextElement(CommandData data) { - sort(); + sort(items); for(int i = 0 ; i < items.size() ; i++) { CommandData item = (CommandData)items.get(i); if(item.equals(data)) { @@ -78,7 +99,7 @@ public CommandData getNextElement(CommandData data) { } public CommandData getLastElement() { - sort(); + sort(items); int index = items.size() - 1; if(index < 0) { return null; @@ -94,34 +115,40 @@ public void add(CommandData data) { } data.setPosition(position); items.add(data); - sort(); + sort(items); } public void delete(CommandData data) { items.remove(data); - sort(); + sort(items); } public void save() { - store.setValue(Constants.PREF_COMMANDS,PreferenceValueConverter.asCommandDataString(getAllCommands())); + store.setValue(Constants.PREF_COMMANDS_PRESET,PreferenceValueConverter.asCommandDataString(getPresetCommands())); + store.setValue(Constants.PREF_COMMANDS,PreferenceValueConverter.asCommandDataString(getUserCommands())); } public void loadDefaults() { + store.setToDefault(Constants.PREF_COMMANDS_PRESET); store.setToDefault(Constants.PREF_COMMANDS); load(); } public void load() { - CommandData[] items = PreferenceValueConverter.asCommandDataArray(store.getString(Constants.PREF_COMMANDS)); + CommandData[] arrayPreset = PreferenceValueConverter.asCommandDataArray(store.getString(Constants.PREF_COMMANDS_PRESET)); + CommandData[] arrayUser = PreferenceValueConverter.asCommandDataArray(store.getString(Constants.PREF_COMMANDS)); this.items.clear(); - for(int i = 0 ; i < items.length ; i++) { - this.items.add(items[i]); + for(int i = 0 ; i < arrayPreset.length ; i++) { + this.items.add(arrayPreset[i]); + } + for(int i = 0 ; i < arrayUser.length ; i++) { + this.items.add(arrayUser[i]); } - sort(); + sort(items); } public void removeAll() { - items.clear(); + items.clear(); } public CommandData getCommandDataByName(String name) { @@ -137,11 +164,11 @@ public CommandData getCommandDataByPosition(int position) { return items.get(position); } - private void sort() { + private void sort(List items) { if(comparator == null) { comparator = new DataObjectComparator(); } - Collections.sort(items,comparator); + Collections.sort(items, comparator); for (int i=0;i cmdList; private Button enabledCheckBox; - private Text nameText; - private Text commandText; private Combo commandCombo; + private Combo nameTypeCombo; + private Text namePatternText; + private Text menuNameText; + private Text commandText; private Button addNewButton; private Button addCopyButton; @@ -95,7 +100,7 @@ public Control createDialogArea(Composite parent) { Group pageGroup1 = new Group(pageComponent, SWT.SHADOW_ETCHED_IN); pageGroup1.setText(Activator.getResourceString("easyshell.menu.editor.dialog.title.group1")); GridLayout layout1 = new GridLayout(); - layout1.numColumns = 3; + layout1.numColumns = 2; layout1.makeColumnsEqualWidth = false; layout1.marginWidth = 5; layout1.marginHeight = 4; @@ -104,22 +109,59 @@ public Control createDialogArea(Composite parent) { pageGroup1.setLayoutData(gridData1); pageGroup1.setFont(font); // create activity checkbox - createEnabledCheckBox(pageGroup1);createNewButton(font, pageGroup1, gridData1); + createEnabledCheckBox(pageGroup1); + // type combo + createNameTypeCombo(pageGroup1); + // create input nameText field + namePatternText = createTextField(pageGroup1, Activator.getResourceString("easyshell.menu.editor.dialog.label.pattern"), data.getNamePattern(), true); + namePatternText.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + boolean isUserDefined = data.getNameType() == MenuNameType.menuNameTypeUser; + if (isUserDefined) { + Text text = (Text)e.widget; + data.setNamePattern(text.getText()); + menuNameText.setText(data.getNameExpanded()); + } + } + }); + + menuNameText = createTextField(pageGroup1, Activator.getResourceString("easyshell.menu.editor.dialog.label.name"), data.getNameExpanded(), false); + + // define group2 + Group pageGroup2 = new Group(pageComponent, SWT.SHADOW_ETCHED_IN); + pageGroup2.setText(Activator.getResourceString("easyshell.menu.editor.dialog.title.group2")); + GridLayout layout2 = new GridLayout(); + layout2.numColumns = 3; + layout2.makeColumnsEqualWidth = false; + layout2.marginWidth = 5; + layout2.marginHeight = 4; + pageGroup2.setLayout(layout2); + GridData gridData2 = new GridData(GridData.FILL_HORIZONTAL); + pageGroup2.setLayoutData(gridData2); + pageGroup2.setFont(font); + // create selected command combo - createCommandCombo(pageGroup1);createCopyButton(font, pageGroup1, gridData1); - //create input commandText field - commandText = createTextField(pageGroup1, Activator.getResourceString("easyshell.menu.editor.dialog.label.command"), data.getCommandData().getCommand(), false); - // buttons - createEditButton(font, pageGroup1, gridData1); - //create input nameText field - nameText = createTextField(pageGroup1, Activator.getResourceString("easyshell.menu.editor.dialog.label.name"), data.getName(), true); - createRemoveButton(font, pageGroup1, gridData1); + createCommandCombo(pageGroup2); createNewButton(font, pageGroup2, gridData2); + // create input commandText field + commandText = createTextField(pageGroup2, Activator.getResourceString("easyshell.menu.editor.dialog.label.command"), data.getCommandData().getCommand(), false); + createCopyButton(font, pageGroup2, gridData2); + createLabel(pageGroup2, "");createLabel(pageGroup2, ""); + createEditButton(font, pageGroup2, gridData2); + createLabel(pageGroup2, "");createLabel(pageGroup2, ""); + createRemoveButton(font, pageGroup2, gridData2); refreshCommandCombo(); return pageComponent; } + private void createLabel(Composite parent, String name) { + Label label = new Label(parent, SWT.LEFT); + label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END)); + label.setText(name); + } + private void createRemoveButton(Font font, Group pageGroup1, GridData gridData1) { removeButton = new Button(pageGroup1, SWT.PUSH); removeButton.setText(Activator.getResourceString("easyshell.menu.editor.dialog.button.text.remove")); @@ -185,8 +227,9 @@ protected void okPressed() { return; } data.setEnabled(enabledCheckBox.getSelection()); - data.setCommandData(cmdList.get(commandCombo.getSelectionIndex()), false); - data.setName(nameText.getText()); + data.setNameType(getAllNameTypes()[nameTypeCombo.getSelectionIndex()]); + data.setNamePattern(namePatternText.getText()); + data.setCommandData(cmdList.get(commandCombo.getSelectionIndex())); super.okPressed(); } @@ -269,6 +312,13 @@ private void refreshCommandCombo() { commandCombo.notifyListeners(SWT.Selection, event); } + private void refreshNameTypeCombo() { + // send event to refresh + Event event = new Event(); + event.item = null; + nameTypeCombo.notifyListeners(SWT.Selection, event); + } + private boolean validateValues() { final String title = Activator.getResourceString("easyshell.menu.editor.dialog.error.incompletedata.title"); @@ -283,7 +333,7 @@ private boolean validateValues() { // check name String text = Activator.getResourceString("easyshell.menu.editor.dialog.error.text.name"); - if ( (nameText.getText() == null) || (nameText.getText().length() <= 0)) { + if ( (namePatternText.getText() == null) || (namePatternText.getText().length() <= 0)) { valid = false; } @@ -296,9 +346,7 @@ private boolean validateValues() { private void createEnabledCheckBox(Composite parent) { // draw label - Label comboLabel = new Label(parent,SWT.LEFT); - comboLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END)); - comboLabel.setText(Activator.getResourceString("easyshell.menu.editor.dialog.label.active")); //$NON-NLS-1$ + createLabel(parent, Activator.getResourceString("easyshell.menu.editor.dialog.label.active")); // draw checkbox enabledCheckBox = new Button(parent,SWT.CHECK); enabledCheckBox.setSelection(this.data.isEnabled()); @@ -316,11 +364,17 @@ private String[] getAllCommandsAsComboNames(List list) { return arr; } + private String[] getAllNameTypesAsComboNames() { + return MenuNameType.getNamesAsArray(); + } + + private MenuNameType[] getAllNameTypes() { + return MenuNameType.getAsArray(); + } + private void createCommandCombo(Composite parent) { // draw label - Label comboLabel = new Label(parent,SWT.LEFT); - comboLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END)); - comboLabel.setText(Activator.getResourceString("easyshell.menu.editor.dialog.label.combo")); //$NON-NLS-1$ + createLabel(parent, Activator.getResourceString("easyshell.menu.editor.dialog.label.combo.preset")); // draw combo commandCombo = new Combo(parent,SWT.BORDER | SWT.READ_ONLY); commandCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); @@ -332,12 +386,12 @@ private void createCommandCombo(Composite parent) { public void widgetSelected(SelectionEvent e) { int index = commandCombo.getSelectionIndex(); //String text = commandCombo.getItem(index); - data.setCommandData(cmdList.get(index), true); - nameText.setText(data.getName()); + data.setCommandData(cmdList.get(index)); commandText.setText(data.getCommandData().getCommand()); boolean isUserDefined = data.getCommandData().getPresetType() == PresetType.presetUser; editButton.setEnabled(isUserDefined); removeButton.setEnabled(isUserDefined); + refreshNameTypeCombo(); } @Override public void widgetDefaultSelected(SelectionEvent e) { @@ -352,11 +406,48 @@ public void widgetDefaultSelected(SelectionEvent e) { } } + private void createNameTypeCombo(Composite parent) { + // draw label + Label comboLabel = new Label(parent,SWT.LEFT); + comboLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END)); + comboLabel.setText(Activator.getResourceString("easyshell.menu.editor.dialog.label.combo.pattern")); //$NON-NLS-1$ + // draw combo + nameTypeCombo = new Combo(parent,SWT.BORDER | SWT.READ_ONLY); + nameTypeCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + //commandCombo.setEditable(false); + nameTypeCombo.setItems(getAllNameTypesAsComboNames()); + nameTypeCombo.select(0); + nameTypeCombo.addSelectionListener(new SelectionListener() { + @Override + public void widgetSelected(SelectionEvent e) { + int index = nameTypeCombo.getSelectionIndex(); + data.setNameType(MenuNameType.getAsArray()[index]); + namePatternText.setText(data.getNamePattern()); + menuNameText.setText(data.getNameExpanded()); + boolean isUserDefined = data.getNameType() == MenuNameType.menuNameTypeUser; + namePatternText.setEditable(isUserDefined); + } + @Override + public void widgetDefaultSelected(SelectionEvent e) { + // TODO Auto-generated method stub + } + }); + + for(int i = 0 ; i < MenuNameType.values().length ; i++) { + if (MenuNameType.values()[i].equals(this.data.getNameType())) { + nameTypeCombo.select(MenuNameType.values()[i].getId()); + return; + } + } + } + private Text createTextField(Composite parent, String labelText, String editValue, boolean editable) { // draw label - Label label = new Label(parent,SWT.LEFT); - label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END)); - label.setText(labelText); //$NON-NLS-1$ + if (labelText != null) { + Label label = new Label(parent,SWT.LEFT); + label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END)); + label.setText(labelText); //$NON-NLS-1$ + } // draw textfield Text text = new Text(parent,SWT.BORDER); text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataLabelProvider.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataLabelProvider.java index 1393e26c..adb0f32c 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataLabelProvider.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataLabelProvider.java @@ -39,7 +39,7 @@ public String getColumnText(Object element, int columnIndex) { MenuData data = (MenuData)element; switch(columnIndex) { case 0: - return data.getName(); + return data.getNameExpanded(); case 1: return data.getCommandData().getCommand(); default: diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java index 30ebad23..64484e30 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java @@ -127,8 +127,13 @@ public void delete(MenuData data) { sort(); } + public void replace(MenuData data) { + items.set(data.getPosition(), data); + sort(); + } + public void save() { - store.setValue(Constants.PREF_MENU,PreferenceValueConverter.asCommandMenuDataString(getCommandMenuDataList())); + store.setValue(Constants.PREF_MENU,PreferenceValueConverter.asMenuDataString(getCommandMenuDataList())); } public void loadDefaults() { @@ -137,7 +142,7 @@ public void loadDefaults() { } public void load() { - MenuData[] items = PreferenceValueConverter.asCommandMenuDataArray(store.getString(Constants.PREF_MENU)); + MenuData[] items = PreferenceValueConverter.asMenuDataArray(store.getString(Constants.PREF_MENU)); this.items.clear(); for(int i = 0 ; i < items.length ; i++) { this.items.add(items[i]); @@ -149,6 +154,14 @@ public void removeAll() { items.clear(); } + public boolean isMigrated() { + return store.getBoolean(Constants.PREF_MIGRATED); + } + + public void setMigrated(boolean migrated) { + store.setValue(Constants.PREF_MIGRATED, migrated); + } + private void sort() { if(comparator == null) { comparator = new DataObjectComparator(); @@ -184,4 +197,5 @@ public int compare(Object object1, Object object2) { return -1; } } + } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceValueConverter.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceValueConverter.java index 5cf6f786..0a754048 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceValueConverter.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceValueConverter.java @@ -14,6 +14,8 @@ import java.util.List; import java.util.StringTokenizer; +import de.anbos.eclipse.easyshell.plugin.types.PresetType; + public class PreferenceValueConverter { // Constant ---------------------------------------------------------------- @@ -32,10 +34,10 @@ public static String asCommandDataString(List items) { return buffer.toString(); } - public static String asCommandMenuDataString(List items) { + public static String asMenuDataString(List items) { StringBuffer buffer = new StringBuffer(); for(MenuData item : items) { - buffer.append(asCommandMenuDataString(item)); + buffer.append(asMenuDataString(item)); buffer.append(ITEM_DELIMITER); } return buffer.toString(); @@ -45,7 +47,7 @@ public static final String asCommandDataString(CommandData data) { return data.serialize(VALUE_DELIMITER); } - public static final String asCommandMenuDataString(MenuData data) { + public static final String asMenuDataString(MenuData data) { return data.serialize(VALUE_DELIMITER); } @@ -58,11 +60,11 @@ public static CommandData[] asCommandDataArray(String value) { return items; } - public static MenuData[] asCommandMenuDataArray(String value) { + public static MenuData[] asMenuDataArray(String value) { StringTokenizer tokenizer = new StringTokenizer(value,ITEM_DELIMITER); MenuData[] items = new MenuData[tokenizer.countTokens()]; for(int i = 0 ; i < items.length ; i++) { - items[i] = asCommandMenuData(tokenizer.nextToken()); + items[i] = asMenuData(tokenizer.nextToken()); } return items; } @@ -73,9 +75,58 @@ public static CommandData asCommandData(String value) { return data; } - public static MenuData asCommandMenuData(String value) { + public static MenuData asMenuData(String value) { MenuData data = new MenuData(); data.deserialize(value, null, VALUE_DELIMITER); return data; } + + public static CommandData migrateCommandData(String version, String value) { + CommandData data = new CommandData(); + if (version.equals("v2_0_001")) { + data.deserialize_v2_0_001(value, null, VALUE_DELIMITER); + // skip commands from preset + if (data.getPresetType() == PresetType.presetPlugin) { + data = null; + } + } + return data; + } + + public static MenuData migrateMenuData(String version, String value) { + MenuData data = new MenuData(); + if (version.equals("v2_0_001")) { + data.deserialize_v2_0_001(value, null, VALUE_DELIMITER); + } + return data; + } + + public static String migrateCommandDataList(String version, String value) { + StringBuffer buffer = new StringBuffer(); + StringTokenizer tokenizer = new StringTokenizer(value, ITEM_DELIMITER); + int num = tokenizer.countTokens(); + for(int i = 0 ; i < num; i++) { + CommandData data = migrateCommandData(version, tokenizer.nextToken()); + if (data != null) { + buffer.append(asCommandDataString(data)); + buffer.append(ITEM_DELIMITER); + } + } + return buffer.toString(); + } + + public static String migrateMenuDataList(String version, String value) { + StringBuffer buffer = new StringBuffer(); + StringTokenizer tokenizer = new StringTokenizer(value, ITEM_DELIMITER); + int num = tokenizer.countTokens(); + for(int i = 0 ; i < num; i++) { + MenuData data = migrateMenuData(version, tokenizer.nextToken()); + if (data != null) { + buffer.append(asMenuDataString(data)); + buffer.append(ITEM_DELIMITER); + } + } + return buffer.toString(); + } + } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/MenuNameType.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/MenuNameType.java new file mode 100644 index 00000000..d1b589e5 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/MenuNameType.java @@ -0,0 +1,125 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.types; + +import java.util.ArrayList; +import java.util.List; + +public enum MenuNameType { + menuNameTypeUnknown(-1, "Unknown", ""), + menuNameTypeUser(0, "User defined", "${easyshell:command_name}"), + menuNameTypeGeneric1(1, ": ", "${easyshell:command_type}: ${easyshell:command_name}"), + menuNameTypeGeneric2(2, " with ", "${easyshell:command_type} with ${easyshell:command_name}"), + menuNameTypeGeneric3(3, " with ", "${easyshell:command_type} with ${easyshell:command_os} ${easyshell:command_name}"); + // attributes + private final int id; + private final String name; + private final String pattern; + // construct + MenuNameType(int id, String name, String pattern) { + this.id = id; + this.name = name; + this.pattern = pattern; + } + public int getId() { + return id; + } + public String getName() { + return name; + } + public String getPattern() { + return pattern; + } + public static MenuNameType getFromId(int id) { + MenuNameType ret = menuNameTypeUnknown; + for(int i = 0; i < MenuNameType.values().length; i++) { + if (MenuNameType.values()[i].getId() == id) { + ret = MenuNameType.values()[i]; + break; + } + } + return ret; + } + public static MenuNameType getFromName(String name) { + MenuNameType ret = menuNameTypeUnknown; + for(int i = 0; i < MenuNameType.values().length; i++) { + if (MenuNameType.values()[i].getName().equals(name)) { + ret = MenuNameType.values()[i]; + break; + } + } + return ret; + } + public static MenuNameType getFromEnum(String name) { + MenuNameType ret = menuNameTypeUnknown; + for(int i = 0; i < MenuNameType.values().length; i++) { + if (MenuNameType.values()[i].toString().equals(name)) { + ret = MenuNameType.values()[i]; + break; + } + } + return ret; + } + public static MenuNameType getFromPattern(String pattern) { + MenuNameType ret = menuNameTypeUnknown; + for(int i = 0; i < MenuNameType.values().length; i++) { + if (MenuNameType.values()[i].getPattern().equals(pattern)) { + ret = MenuNameType.values()[i]; + break; + } + } + return ret; + } + public static List getNamesAsList() { + List list = new ArrayList(); + for(int i = 0; i < MenuNameType.values().length; i++) { + if (MenuNameType.values()[i] != menuNameTypeUnknown) { + list.add(MenuNameType.values()[i].getName()); + } + } + return list; + } + public static List getAsList() { + List list = new ArrayList(); + for(int i = 0; i < MenuNameType.values().length; i++) { + if (MenuNameType.values()[i] != menuNameTypeUnknown) { + list.add(MenuNameType.values()[i]); + } + } + return list; + } + public static String[] getNamesAsArray() { + List list = getNamesAsList(); + String[] arr = new String[list.size()]; + for (int i=0;i list = getAsList(); + MenuNameType[] arr = new MenuNameType[list.size()]; + for (int i=0;i getPatternsAsList() { + List list = new ArrayList(); + for(int i = 0; i < MenuNameType.values().length; i++) { + if (MenuNameType.values()[i] != menuNameTypeUnknown) { + list.add(MenuNameType.values()[i].getPattern()); + } + } + return list; + } +} \ No newline at end of file From 09ead75d3f2bc9e398f705106e832a0e50bc1569 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Tue, 19 Jul 2016 14:31:22 +0200 Subject: [PATCH 16/73] v2.0.0 beta 2 official release Signed-off-by: Andre Bossert --- .../2.0/2.0.0.v20160603-2346/artifacts.jar | Bin 734 -> 0 bytes .../2.0/2.0.0.v20160603-2346/content.jar | Bin 5731 -> 0 bytes ....easyshell.feature_2.0.0.v20160603-2346.jar | Bin 5133 -> 0 bytes ...e.easyshell.plugin_2.0.0.v20160603-2346.jar | Bin 13935 -> 0 bytes .../2.0/2.0.0.v20160608-1116/artifacts.jar | Bin 733 -> 0 bytes .../2.0/2.0.0.v20160608-1116/content.jar | Bin 5708 -> 0 bytes ....easyshell.feature_2.0.0.v20160608-1116.jar | Bin 5133 -> 0 bytes ...e.easyshell.plugin_2.0.0.v20160608-1116.jar | Bin 13935 -> 0 bytes .../2.0/2.0.0.v20160719-1230/artifacts.jar | Bin 0 -> 734 bytes .../2.0/2.0.0.v20160719-1230/content.jar | Bin 0 -> 5741 bytes ....easyshell.feature_2.0.0.v20160719-1230.jar | Bin 0 -> 5133 bytes ...e.easyshell.plugin_2.0.0.v20160719-1230.jar | Bin 0 -> 104625 bytes .../updates/testing/2.0/compositeArtifacts.xml | 7 +++---- site/updates/testing/2.0/compositeContent.xml | 7 +++---- 14 files changed, 6 insertions(+), 8 deletions(-) delete mode 100644 site/updates/testing/2.0/2.0.0.v20160603-2346/artifacts.jar delete mode 100644 site/updates/testing/2.0/2.0.0.v20160603-2346/content.jar delete mode 100644 site/updates/testing/2.0/2.0.0.v20160603-2346/features/de.anbos.eclipse.easyshell.feature_2.0.0.v20160603-2346.jar delete mode 100644 site/updates/testing/2.0/2.0.0.v20160603-2346/plugins/de.anbos.eclipse.easyshell.plugin_2.0.0.v20160603-2346.jar delete mode 100644 site/updates/testing/2.0/2.0.0.v20160608-1116/artifacts.jar delete mode 100644 site/updates/testing/2.0/2.0.0.v20160608-1116/content.jar delete mode 100644 site/updates/testing/2.0/2.0.0.v20160608-1116/features/de.anbos.eclipse.easyshell.feature_2.0.0.v20160608-1116.jar delete mode 100644 site/updates/testing/2.0/2.0.0.v20160608-1116/plugins/de.anbos.eclipse.easyshell.plugin_2.0.0.v20160608-1116.jar create mode 100644 site/updates/testing/2.0/2.0.0.v20160719-1230/artifacts.jar create mode 100644 site/updates/testing/2.0/2.0.0.v20160719-1230/content.jar create mode 100644 site/updates/testing/2.0/2.0.0.v20160719-1230/features/de.anbos.eclipse.easyshell.feature_2.0.0.v20160719-1230.jar create mode 100644 site/updates/testing/2.0/2.0.0.v20160719-1230/plugins/de.anbos.eclipse.easyshell.plugin_2.0.0.v20160719-1230.jar diff --git a/site/updates/testing/2.0/2.0.0.v20160603-2346/artifacts.jar b/site/updates/testing/2.0/2.0.0.v20160603-2346/artifacts.jar deleted file mode 100644 index a777f2112d1f0013a3e796a7c37282b905595399..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 734 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 aH~t@gSXTq**?$BW|Ax%Jm5k;;-TwgUu-G{O diff --git a/site/updates/testing/2.0/2.0.0.v20160603-2346/features/de.anbos.eclipse.easyshell.feature_2.0.0.v20160603-2346.jar b/site/updates/testing/2.0/2.0.0.v20160603-2346/features/de.anbos.eclipse.easyshell.feature_2.0.0.v20160603-2346.jar deleted file mode 100644 index 237e98f48b9bd52e2605a902666c04e42870bb30..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5133 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 LUVVT5UwZz3FYSez diff --git a/site/updates/testing/2.0/2.0.0.v20160608-1116/artifacts.jar b/site/updates/testing/2.0/2.0.0.v20160608-1116/artifacts.jar deleted file mode 100644 index 902c447323fdb5fa2fa070e4191b4cf45447cf14..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 733 zcmWIWW@Zs#;Nak3V9h$=!GHvK8CVz+i%K%n5|c}c^(u06{+(iAI2-2Mf6G8%Z}_YF z4~$m}4hU>o7^3Q0{bJSLEvpaB)1J%|xxMf0ExuTXKi{n!>{Rw$lv_2&#yEdo`lqx> z4_~N0&EUIbpy~8xqMnTNelPnG)Cp!0q3+zofIDVNGg0#Pj=cTa8;R=bLAz0!$C(EE;?!& z_eMidN=sMNLPH|u#-*j-xA&b2y>qNEVp`KilTbaur!$SK%Ksjazr*@|x8wQ4b01&u zSmxDiC@?)@wXp@?$z^k9K6jV;TbCenX0N1ix?rbei+tHCt8Hylw5GbhU&VE5Rmm~N zvl81EINzyx-u1I%mf-SZ8zhU(GKJih&Frw;5>TvG>Xp0Vj;TW4R)a}1Luc|9CQtqT z)AMtw`$wI`LnTt$V(aV8!gkB8KdHaUvrpyZrd6M%{=NRG_k5<2!PS!$Znx^doz0?WFARy zhz4h_`dG$&;0bp_&i%^Vy6Ppb=T)wM{dM=>cMIND#_eBVZF0@==^goPMdeR6Ud{O} z|7StYN5vSO|6F>RHM)9Biv`}goc5_*`|V)oC-a5kOLVw)>bzdJ^7-X=yW*bRG1+hX zuk63YzfZM6-W#^J7X=rtyqsjAbz$=@jmLRn?*FR_S?0aJzo2*XhW{>7uKw|X(&|wn zo{5e(I)Cq*UU?_&q0XXfPv7ax+~t*W)sSDJY*jo{`5*QGZ*~sz^HF;|nHU&$a4;|g lcr!AIFd$MQvK%NSq5_O`8Q{&z22#QZg!VwX186J*0|3eOK}!Gt diff --git a/site/updates/testing/2.0/2.0.0.v20160608-1116/content.jar b/site/updates/testing/2.0/2.0.0.v20160608-1116/content.jar deleted file mode 100644 index 28967df86567015e14f5e828e5759a7ee67a7a1c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5708 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 Cv&=I9 diff --git a/site/updates/testing/2.0/2.0.0.v20160608-1116/features/de.anbos.eclipse.easyshell.feature_2.0.0.v20160608-1116.jar b/site/updates/testing/2.0/2.0.0.v20160608-1116/features/de.anbos.eclipse.easyshell.feature_2.0.0.v20160608-1116.jar deleted file mode 100644 index 06c595476dc4c48375c43ca0964c0665faed7d7b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5133 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 diff --git a/site/updates/testing/2.0/2.0.0.v20160608-1116/plugins/de.anbos.eclipse.easyshell.plugin_2.0.0.v20160608-1116.jar b/site/updates/testing/2.0/2.0.0.v20160608-1116/plugins/de.anbos.eclipse.easyshell.plugin_2.0.0.v20160608-1116.jar deleted file mode 100644 index 84815f02b6b55acb9a1399a1c8a2393887463ea0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13935 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 b4gXL5FH)?ojEeT}0@6Pr{!gYL`M3Kop4k84 literal 0 HcmV?d00001 diff --git a/site/updates/testing/2.0/2.0.0.v20160719-1230/features/de.anbos.eclipse.easyshell.feature_2.0.0.v20160719-1230.jar b/site/updates/testing/2.0/2.0.0.v20160719-1230/features/de.anbos.eclipse.easyshell.feature_2.0.0.v20160719-1230.jar new file mode 100644 index 0000000000000000000000000000000000000000..4349377a5a0feec441a55642a48f63c6498f3d6a GIT binary patch literal 5133 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%0A0;zCoWecRLm#(`S}Z=}1vGo--sD8*Rc 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 literal 0 HcmV?d00001 diff --git a/site/updates/testing/2.0/2.0.0.v20160719-1230/plugins/de.anbos.eclipse.easyshell.plugin_2.0.0.v20160719-1230.jar b/site/updates/testing/2.0/2.0.0.v20160719-1230/plugins/de.anbos.eclipse.easyshell.plugin_2.0.0.v20160719-1230.jar new file mode 100644 index 0000000000000000000000000000000000000000..6c64c61ad18bd34092f601a953059ed9feab1559 GIT binary patch literal 104625 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%0Dk{a+mQ+Hukf;!(tN}{ z1K<|TDD6V9dD6kXjof1D`fg4zg^??7FYZ$}%Q(N##mFGGz=;KNc&PfZtuU!E)n_c| zx9{MAQFfo=@Y_f)0)WC(DY(E8$cdJM=>lkQe(I zjy(z%>w+XFF2iLEk8>zfH(*4hDw8ZVhfRntBgY=-Wc{)PE;D72 zvwhd4L(bPK;HkF9%`QgLF5jS%YAHAq-wk$5zPmhYfuys-MNMYRHZf&|>;qejR$V(} zR)6JLkfIKgWkwUvcn)O?WLnUt4q}=zYh?(uYa6h|W#SnGtFmWh*lz;jWnKu`GC$+p z_n41svv*C=Z$kmj_%4fi82~#JNWOf7rL>&qpWA{$rR8Pau(?Tert!YJ6Lu%VF3$HF zAh5dq&Mf48VY%l-*4^nZuoc#B#5mf1B6~yb7bPIE_CwE|5Mxo#S=OXKqrhQ5+NxBL zFk{C2{yfK7N(+jKG|%g`IFT9|MJKQp;Zbk=HKj=`pwcjq>g5%GE)7Q}%*6|7Kk;E{ ztX~>q%`Vt7J;?PQNXU6@%Z`u8!X?tB;BY^$C@z{U%^>F_s^iS%f zF*nh()wOk@HPy8(Z2_&M7^|jjysx%csekx$`|~^peBR97?IuFl$j@7!c3PWeL#LCouZCTcrl99IxQrNc!C(!2-9ITnQ4jBGdMgEQc&iN~=Uc~pGql=TntK(M} zrFw4{y%BeKYj|VfWu@=ZR~;9mTN_l%Y8HFrkFUA4_;x`M5^kzhiAYw^6z~b(XkZvzto_!Dph~g=u*yD=_b~OyZwlt)KOX4v8vefv^GR8Un+M#6KvRR$|Q}6~NOBMZ! zx`;j9IH@Nb8el%dkl>JC0=5Xnbu=z@wzPGdKu+>x)3WEVrXMR_MeNoOa#GXqAjb*> zN=x$H^pXNC{L!(Bc=Wrk?dA{46TVClKwsx^-x^)b9Y%V8$GNUH?P+`V;Z^YR1lIpdw4J|0~r0(2NAe?==@E!OOLVx!u}4CBs~Vr z8dCoaum#`r=7+FM8h2R6`P2nXX`58TF^?82>#wSa!-Xu#g{)oQA76n$s989&5r!qr z=fRINPo}7ZWzjalHHcJ9b#5JPe~fv3V=PUkeA0q>n0{|eSnyj zN7){fRx7q2OCfXNw@4@}6X<9tjc*n7`EQ`jtnb;WS}OUgSR-K)*aW`#9pbUkw+Sa| zU0NhZ-He#0!wP*5x}u~0tfwK&Xrj-U;_B&*VB9!eilkjAO0OXPRO$giW2ayP$7*MHoS9a8rHc!InKQSM(_sOVHDW1XDGBaJ2N zbai^7b)=hUGqx|mWa6*h#9hsXoN0waS9gcr*K%32>S_xEtAl9a4f>$$vRX=j^-5@5 zf9ih`#kKpAYy$!T4kQ-zW`z4fKL6^3x%c+r%_7*Z(qHf_)Bn+%X6^td8d zD_Y=_ZPDlHmD3KS#8El{8g~L*lihFph%oh8V!m7JWW6uWy22N4*X_6Blf+<%d_)*# z;6!m=xBD0mn{nlvIszTrcPWOhDLiiUB;#jajScK{<^s#jB zE>=hU6+ic@btY+q4ssz*oV51QSCwnmn>2x&pBUk^AAuH`lrDXD7|u}gBDtzzWN^rY z4madgu#e&d0<}Hw%l0g?N?2#F8Z>{^-UnE(*(oiReqG2oC_#k2e>xGl;cEXyk$9%x zYMwm^VcpcnSo0KtM}Dw@p2S&P0}|S`l+O~;^g+DvLf`1tL;zCVWg*z3Pb8lxX^zrq zS+{0sPH2uriEJz}q#i+VcXirA?g) zYQc9;Nc1j$?rh3Pn>lT7f@qu)@kJ8T3a_uRO!B#E;s$*0_qE?skML}%ocy^}u3OrM zPh@Mya@?&Z$(-l$xi{YtdP*(6onS)kGG{Q#iO^qfKlTb-7ehm%caIGIyel;&HDm_b zFHUERVcV|dtT}&o_nn1SXTTJLrBT9;PQOMe zioh5~p^qZ|J%?%&D?Ni!nrU++bb?Dqda5M?gmj-_48JT>y{<*`v)A-X&;cw@p-!I= zI|*4vy=)l6SU~mZD;cK;;q7_Lj~l`U%|KZ~B`TqqM)#n`$`x*c-JXO@mhYdG%FxOE#b>op5ne|M=&@l`twpI%@ zYUBVKNJ)X`;Yd?#jbKZPRy8+PfuP9!6GT!|JB7nBe)fRvh+-A&KvLpnRiAEXC2kR} z){9b>FO4`?@C~nVGdh_)(zel?_Tsa!9f^ zSX;y@gkAHh`@>zN=1WLmqUn45nxPT}epq~YzCl1^ICFYzym8vo7bV-h8pZT%?>j8Q z0k1T1>XmwdIYonj^f-yd0qfU=%l17|F9ylUn*KJ!)Dki2FPZ(aj!03I@i49rz6k2T z00G?pd)anUi}5SLFAvw=R8TY5aA=UL4d8eCm+SZ6NU}XI+NH?(NF$En{d91B=fChY z>x#cNmo}Infq|_we8J(XRdcnKq@pVB^5_4?TmM!(srI&y-Z8@O690o~ zc$mjR)U#Bn`;Gx% z56k>qpmexcSlMwlE@|~@1D+-%U!<-aW;WcHw4XOFcglOZoFi$mayNLrG4<(5lWLQ0 z?$tQH@q!UnHASO@m4~O&SY=dFdu9w`b6r ziVT;6$jul5tea~8wDA(XkIYhkzSib*3x#y5%PQgptR682L^`U zPl0Eb+$U7RWr8=M=ertNOKd6L!&ho3lwKH{!U;!r0ZJu=eXZ+r=zWZSSauoC`CZo5 z!vw7w7l)KP=9E=bRRy7A6xJWbeQWpD)vatO%bI`&;BJ{bbyC4*h(1~gVP(Fn)6?eP z!%_=&X`>jUn&ZXmQDUzP2)h~DLj<-!bRyHHir|MZcR;XoN_pxAI}@i2^&3rZ1y5{) zt5qq66q)1L?#}U6i6xsRU1nMjt()~14Qb$s(Ky8!NgQHkFsyPXZBo23Z?mdO)30;l zyGTwrw+2;@k@?YZt96gX;JmG`1B?_R6imuqua`k`342bk2dV0aLKo9fjUaw5963Sb z(q@*yig~EGawDL%qHjSd_(+tgv5gFPAvJMvsdDLK6LjlJH@AZl!^;I6bKw@!{O|!g zn$a{-B8dv4WTQI7bN9_nETou{Z6UMgmuz;4n8YbVpc^OQkaxu6q=p!A)$w z@20;!&${hZ1>OquefWH3FG0GUu*TQ?xbeARo<_5=)zP6gLr|N*VKjq1m3m~ioTOwV z)FUTdG>)-#-SRy$xNU{gcHuj^#diX1=bXIsr3wHgC=|Yi6%JFI;1D*a&oJmiesqid zK{@&w(XZ_I$V#%UQ|#r|h-Mby!VxUy5skSt+^P+Ca(u_^P3AU--M%5nHp}^B&K?D{!jfd8AyF9xOraPjKr8UzpuQPkW=N`x=1qHKs zzGCR?b^Jk_Ch2U?{CQnLc0t30wgX9#x2t0EzcO+;5$G=1fHcm9&awPg% z4y(b=ci_!Oxiv>_W(M-^nm}|#il&x)6-pRDFPN&$zR@2~_STNfBkEg3TN&zYYZmI4 zX?I{FwPO3Z{2n;Wlig7Ono2HM#9D_}X~TBWorvE^fmkpF>Ik3(aylb`SAl>i{Lt73 z;t!%LnnG?i8brXgr{I<&^!C=<4Mn=>FRJ?~x5w|s>sx|(Kn8XK-+;G6hUA%g9+s}| z9@p3pNYn7ugu50-j4VDuuPu<7pX$R| zk7)0izGXUT4)TG}Nq)sfy63N_9++zJiwaLEknhNBT>7=D{ZzLXn&>uN#u(h0iyJjF zTlXBZH36s@(F@PCD&aTg4vs}B#h(IEM-C%-=bU6v41S$v3&P8g(6cV$~UJxO6Uaiqdx6- zx4k{UB|X_%IYX?^{zXlSJgKsUM`!9o3+>4ohpO>zW0sGbm)>me#A>o z0>gt`Bgm_I$dCn+jRpXlq2hoS_cG&;eO2=%HAkor5nz|4dQ2g@|fkK>X!S&)xcj+YU;94{{5VkAIN9h<@;7yi#}|z1*G>FD~$h72VpX z;{eVE*2YOjS*A%|>KK80N3Q@d;&&aG?+AoL1yUHp`aZak z3eKWMLyxN1m6KK31in4)XeWwu)QlxA^_3S=a_Al~3$_sI1=i}%vtvtC^+tePWpQPJ ziF1(kPLfZ)gJE^4b|Mvr5RrkEm=h^eoc_2s3@ zi&>f@WVQv@#1h?%tGnMaq0NUha*(cF!;z-Rxd|&aLCoPY3X2{07}gBHzk!Vtm~%yI z6Quij&uoXO&!Sg46rTqU4de|oEbbybDb;xZj$bmyTB7NAnyBG;g6AenpD2Sfk~XfX zdkpw?o8pT7B^k}c=gj+^QA7XqQ5~j)3Gn?+Ua&y>?TzuOlRUxJwkW9Zl!DrH_m;zx ze!169xjbo-a#@%&;e)qw?P8 zWJx6xMldiXb17h#oR4MPE2bmfv5q#!?Zj6?JpD4WVt6)p{G~B3@2 zapvEyyo-Lo-#1u7Gf@k?a5lv;apK84URx~;5inMUn2kT`b#|g8`U-!AHQ?Afc8!M;)=~srvD2vK+V6<(;l~NDsV#U z7YtkZD`gGrKB|{sUv+u{+09=e7Nz=_rl1~sCj=|a1LvAeL#~l?Z9;moFnn;|q!hSE zaR{fa@^?cBEh-1on#)jhKml!LDGUruLZ|TgcA){Chnmx9F~OWZWY+gjqgf&|@D>lp z4Wp;Vh@BBTaCtQeO7y%Fe^b8f(63EdM6M<`3Eho7M<4x_q`eI*_LRvKGIu$RI|5!2 z3rrDXe^Djwh#UHMoP{VZk@3cuyk8FU?EeO#vYxzb|Ksni7H9G(&?|CdhTGMfn-xf__T-oHrVO zxhs2q;D13KPy-KFI4-c7w_edbW7OWCF4pA?#62K8^ge`n!an(sC#M7i2NmK=q9SB3 z*r7P31C{HqSI&Ai^cP8PwLkGT97cm6t(C1|0eD z4Iis$Afl0HDj)G02QuhL%MUXIk)ckDZO4bH;b~V7C^slc6MkW1Zf>Hr)aWZ+8w+mq z0Ep=1dDx^yTAI8OlaoSnRF4|u_MZ|=3hn13qP^u}yvE9mNhD<|k;H1KXl>JuytHV~ z@NNhtfvr%Fhy?hC8_(5X$0YKdv-^#a{+Y!e?ojsW8TH8@og0u#lK+L?xq^Z<)5Grr zSXz*_bpRZ**aT0hB}U*olRsz_6ZvKx0p(0!dRTKVcjY4mwG~+*H&pMP)(-dJLR7~< z%ntr!&^O$@iHN^w6f~+>ktrV2t3atXoSdwsDLlKB7Q@7lNv9*OFM+vPh%f4_CR9W} z0y$iz3QxJWB8F>H$z#G#ARfPU_eF+tkzt8bJX3OhjIG>PRgqUpiSOHb3(Ypu4Bq^h zXCaGPy_jw7C{HW`Kz4v^J3^5aUwP#11~Ml-T{#ExUyHsXdylNhop+Ky;m z9%1aQR$l^Vip!VSo3Ou?rmOA+Pz?xISWTg%=?Z^hRq=Z3lhs*t!WwZfuT6t5LA1 zf~rc{-Bz?CZk|HHX#j@eR2Z@9ST|w3mK8G5kaba?RLCsJ(XnVuA)0EhBvmBgg`i7# zEo9M#t!n3rvh`%_6h2SoolC|A*kJ#{dUH!?n{n}AiD?O!-<6Wn zW5X69=*b%LEGMHs_*^OwZ21Vq?nz)uw?9WW9X@9M+JS`(d7{AW#`!r?cxo-BL~mIh z!1@i>j%{x9`tT!XpLv{jJKbF4f0FYANy+f%4T-Q|Je#0t(^-Qp8I!6e+>=Gk(gwmqLqFkVWLXT`b;#!*vH?s9bs|f#}OVZ|tl#?z*~Aq79AV z=!sxwf|+W&S>u9(R6caZAd0${I_}!GM;jZG>N|lJGG`D5W4c+_msDv);AH8#lgwOb zv$MCG-Y|=TFCOl-Y-JN#t$uPFDob0;(!qOH5~QhmP$P9eE)>T*E$)Lt1*EX%pu9TB zsrt(fGVkv+9qWdS4IWgDEjr3HQ!>eB=k_Pk4PCJLF)b0X>)WEKmnDT{kQ%j&4I94^tS(_;ruXI)XDrlO?T ziuaqxFE`d7@0%gzP>=(p1hJ?8g4WA;IXQU^aKN;u)GSf7Q=^UTsa8G15s)$omV9{D z_6rhDaSjOxvq0)n$rBRjzSK{?;;m433ZcT?0-Z%RMq^6%(;_E7!!%U>;jwJ#bF224 zqr%+>o#khI+u>wBQK6y$?8m0+s&8%so;(F@8|XX8C*D`rp!AusUU#go7T&OH+q#Op zpKF_C>f+s6O70aKwLmS&ZCztaBv~G@LpF&w<}P0@mYj;SUNvfqOyX!Wr)u7*_MMXG zo#h$2_GGguS?319#dwI=V)tNnA?`3?6CL&`A_B;up*JJYV7&xao@7cbm32>up|dAp z=?cy9`PJ$b^!LtW_@iCR0c7M`4NPDf8LHhNt132`Yh=dHuYZsY$?2~)SZDx%R=mF> z8^8b0{wokNHZiv`7W~)npVXsURZ|s775N($m^4Tpp*o{Q#dAT39!Q6QzYAblZ4inz zqS`ui?3c&@@st$#qmR62&(76X`3x_(#>)A*VD9@Wp3+D5m>+N*U}dFI{3SiNatQO5y{p=>g9w2tW&_T^cx+Uf%rZ;I zVcyl~^sc<1SRRWmcE+}PLo~u!l2)PTWMYivN%nNt0m_wsg6LbEx%=CG8=rOO)v8V? zpEGq10=V;WBV&NY;#nDgb#DZ&#u-gC^yof?BR&}jrssW1`b3(rCJ$I3f$gdbhyst~ zGd@Y(GNr^qB9nay4~IZ^sR2);m!q-$VoQ-_(Z_g#fN-ipBU*~M*o=|~WA2N>T~tW2 zke6$3Z~=Cb@EN(KXnFO-<0Nkep=_mHY{(LzwCjpP@BO8Gu-ph{6-pSicr0{UaTb~0 z;69X|jfSved<&1dk`{PX`D!-oaJfDeGz>&VE>~qCNVU-UD8srgPceZhr{HkC z|HJ&f0%i-;rG|!^P#p}H^JTxyHa_Q$Wz6VxJs?i%+S>6udg`IAX@vA1x;z7I%~c(YN#ek?k%V5iy`*h``XAOBvUXEKaRvX@@&UNF}zs?g##rU7rL;h zA&pTmt^H*FuK`J*100Www`xJQ-48^pky=}h{-(1BNV z;oyZzyQYO=^|7Cy-!bYe-9o~BJp;;|yTQ~xaH2{$RnoAw>P_LKmsU_5+Mc(CNltn% zxX&p^>jbk1cty(4kRlVdMY%4n^-NrPggHFq(xX-=YrU?0#pDGyY6oKSEScNp@Nk@FnQ zRzl$}RGsPPPB^7V3wP6*C>5J`^VC-x1jtU5x>T;pQCfVO`)^4W#k7;loyCHXO*A5l zQA?1pTvbJdJo|R%@tc)%qnteeeaBV9S}7Zc=E`xc5-^73e^*f4;RNnv{J;{w{<3J1 zBJ@fYKuHXjAXom}_Je0F$Vt%A8Qd}cB#Bg$SHW*_s8&eo4iEXhFw5%g5Z~PCbOywF z{gGothS};R4KcZ*GmBi_=40n_tAPPVbEwZW%5@TqmpRsppErh4P7&+Amvo z64)KD{*C-6F19xCxlhNL!@x`k`(ibxB`^G%xiI>PIUIOhzb@LmkD#d_^-Cq>;Y-U@ zKlDZsOdS8ZmyCp`kEK6V<^UQ)ZTiF~i^TY1HJ3ZQ)T}#rd3w*>;ZCYo(*0U}Ivra* zwnEdYhXqDpz%QgK1T`LQ}ruQb&|wu=jE1#V2rH*d8RcR_i9My-X7q?4*g>-0y}R9jKNRF_i2c6(!8YV zujWTV;vEuzXMoCEihN&8N51qrpPFRheMTjbLFX+^aVfbYS3y+5tJT*!h(XqIV;8>s z!R`UOv+#_(bJUKonKMVgvBX zd5e_hD2L0)iggcCAh`b<(w7n%^_C5U!$A-xufJQd5*0E@bsAY5b@XM$O}fhkiGRAk zkalZFQXsqk66ukr`85*X=ygzYIDtnsX zPRzCo&3Nl%p?;ng!d#k=3s33Qdp-j$W-{hFErOVvwq~KJh}k7oBpxM+Is!+Vl-~QO zg-6B$I|R?MK&)1|+FEj>L{1V!H)t%X>H+R-kn$&aOD9{cL?E^dwqAHOA_rFxPDb`??>a3#M~ zyP8~sG6I!b7y}R?edd(%om1h(5Z26Rt9I93(?-YEZ$Vu!!I9bkYdZ&2n?6UHMgNK)0!hUtj6J97A6CIL)Bb0K-z z`I7RsfqkqL>Yx+hg(C>G0bt!D_JHr92O38opml|07`ptrMsE@C83(AuR5AX9L<#SC zV5p>jX^y(0|B3X<-D5cfgSN&0ZIC7^!_*btHFV2*j}($i_}laq%v%>X%4N-z9DO#{*$0hs)y z3xK3}TjCq$9}ZO3Z#}XP2mk;G`ajS8gxqcPt<4Qp^c~Fg4Xlh6j2&&QT#Wy9?3}H% zVY49u&qFmwSUlS>uqu(cYHs7=6h1g;Q{$2xd7uTb^y|DIZc4DO1dS0XLP<?B{)@$1_n+CVTYXfN~ocuO~a50}js%KZw#&h##UA9#h zoNQTMPYt%;CgcP-zb@3=&gl0WICkLhfX$%YzPc%%6BDdzsoh_Yrhq{{bF3BN-VZT5);$SE3 zocftpi-6Dubm9~03uux_<2pwGGZh}BJXWc+`ByX1dp*``e9QuLB;Fx7n9t>NP`8N4 zu^05itHcOK$S{IfI(wuew1?^-R+lKtl+s8Xqn&?#8iaB{I0#Z?n~*}JD$sR&L*vr) z-nDx9mt4U_WqMg*pPg6g2Um{Udtpy%c0{F50wrRJc>zc!A_@J4xc`S7+X$a`!Qn8y zpgHcD1Vz%i*DR6`wWd9EQ#)GrC|5g%@zpz5(Dggatf<*LTHVW#Wm4Q5s9FEj19Hy55#-w;X!e25_V*qt9w)x=G47v7VRg* zgKE-FeEa}&G>9{E;DH60k-B=CbR&0mS=J*?OvR%d{2Ow{u!V*#(bF!9p zpK`JfuH>Wow7d|A?gC}3Ws{}fS73w;vg5sc5sR=B<%O1++6oeCPhOTTCQDUjx;b_9 zIgE>+Qm_RuZCnW&Loi5%L%i7%a=ip#8iJ;rQyO7D0h@BkLkglI;%j;p_taI0GuK3! zIACQu2f>t!32Ko$8`D!U!iH&!Se74YG>w4?QX|#iB_%CFBd3ugCqp8%! zVP_SwRVkv5;!CA;@`UkvPi%9NGnF++^nEO>bN|(kb3lp#+8w}!`K80M2pDH=k&&h1 zXf{xF5;OgP;L+RZ?|=BaEgsroAP@k6E7;%pJNJL&@4`mrPPPtm4z_m24o>b$#*R+^ zx3g=?BJm@Cm!PFAJAhHJQM{z6sDL0)6oAgbM#Cg3|QVKP0Le4BRt!^G9|?ezt#hYW}OiazWpaAdNaP%#VLO&(0y zwwVN?k8UwXe&no}J#`jiOt-2czdC)K5EoO20*s!JlKmTcfjZORH?lQBu}!)H4{om< zOL1lg)6{M(SqcUqlZs5xo+x<$eg*nDV+Tb}^0rBE_h4g)p4p@tCR<8-b>~g;ke}i# z$$-$Y!{7ofpgMHAn@O~--O{d!j(3hWQbrOJ$F+RwxuC6&Q1f9skyxjNrkTKw-N%|+0`*%YN^|T7 zl|jPu=Coq5bm{20oZv_(b-d=WNVtY}3J&QopoUWOc-)1A($LN*t$1eMraeOFbBJ~4s=7)th?N zeDi-WB_J0*y{Oepr?4RR*Ii0e+Dv~Jjw@3nYNU_G?`YK^w02Y3yl12r@ z5+Se@j2O(Y#s{N%$=JRLo2hGmyzkN!WF?yq~JRhg|XP{;wk^E*YDC1shj7+AY6zrM!7j)1lt7L-u{hKgmP&*w_M2Zk7 z;}N9HD-&tpjjm(JkoX2$$JTKm(X+deAS-qP!Te3O2f#p59f(dEi0d5r?;rGt_~Zl6 zA)dW4ftId`m$oB^S{t64D@aX5rHX+eoNsru_~ zI~(D^HcW>fgmoiZtPHP+k(hrB)K0wvBkturTEyq>SgxI@JZWw-C+ypkWDd8%c(+t> zB{5ICx6fL8oxFg~b?|~khYI2#W=|vKTPoPSD-AK=%HF#9t1FxswRkC>D?*e*-Wo&V zh9Q@gGQIP>co*gST^B}?}ko3Y=NLp40(%{Sp>Ev2?yf5KfeuVWIh1;7&mzveFJc6#B6#tcdN}5%-yEx zpZmfnekYd+)^J!fXnS}{rAKg(@@M7woQM_hi&u(d2y+$ka6DiJ_K5hFnoA4g)f$AU zbX)R$&|fLFxACcIuOT2hz8zkU zqFKluF^&OIJK3?NiaXo=xK?q`5bG4CtvFy*2Rc7P`NIe)O@YbH!$=4I(f7FfZ#1Ez5Qo8H`JK1UVqTP_ouxfVktu)(i92!1up65%PzDQWBFu zxB_kv7lX3|mzF8S&48PNU*c6+zVa8oo4zuPuSEX*S0$W=SNUk|U)TT*@ju6gf3KhV z7d!~*JL&%u8;Vuk-H=uget0CGCGMGA?Vy9&i2Z2Rz$ec#0QMjqpj{Y5{YjNlP&M(Z zk*_j{#4~|1wu{ZzN#jV(=YiKlSWAsD*O|@Ni==BG|J?Y#`~F<1az41kA3jx}JfF;X zG&VBzq_Z*EZeMQvxF0D4Ox(f2umEO@^I)=pHkc^M7AbNl#-7_h1aTCVF3f3pxX~L6 zIl6zv<*Y;p*@&dTY7oN2-pkLvzSCLWs^U+$CR4FaP!!!72 zC@JWP$coqOjF(3B(fY&x%Is*q5RyStn|t`dsTZ4%dPZpmFC?{uY*Mb?*pTJ)A<7|$ z#N1nLQB|()QDkczcni8#TR}`Of~jw?04EC&2L6!Gv#}l*Q@;qhZH;WS9N7VrD8EO&H$hN09q0+AawIBW_u`L>@0AUc;qG6JY{LW{P0%VY?R?nYB zRbNjkRev=|2oabuSZ^XiMej*DFU6Grv{(Vh;75=|&i`GA0uLES@HZ;a_4}BSb5HhQ zR8ZeB`+hyKqr>KfOGOi=2d~W;mz8C}y~0d6txmO5$f-j$+l2df3cBmGM&cfD&0U+= zYq!bzT0Mzp`EKEoRY{upuo?Zx^49q|!uWVhd`ZT2$7vO=rIb4TI`V=ttYrllRW0Z+ zWV*4kT~aFd^y+HM6`~p zPx--Gmi8J^2mii%ZA~8cYtdjSU&zIL2ZI@m`D+uOqHr3#%mI^@9UKI8&8c7KOV;oS zG4G5q7W3mliU8CeLe`RjA{t4| zo?BSWb1Ctkpwg@Ros1ci7W4rOe`_6dq${rz;_G2B0jCw;^k{Eky@8_LY@64r!R)rk z@>=n%-7V@qN2^_T|7&p!^c5K0q*wfFh&k^cMl5uMFzIo>PKFqX&B%|m_mIIacA4q} zGj1NKWUQu|q{QCMANdC2^u>j8sd0lbb>k)9TeFeAVz5+N?cv*6aW7~*vb~0Z`cX%! z12xP)RI{fhw%9VoiCPzcwi0P|Z7Mx8fdg=Dh=#a)UI{+rcSN6Q9>wb>Hw39@s?*)6 z_gJqKcohdyUsC%guOK+1ZnUM2Smw1BbTJFsT0dJ_saslHTUk3cAy+N2K&50UqnMLF zfrEIpTHTY4qChEa9DS`o6Q9ESwdcF@SecU2HM+|4%gC{m3*)rqB$vq2BTh@RCk6m4 z+|EeK15B+N=DaFYQ_U9EcCXCt70Jhf&C_z996`)Tji)b|e3wMLj@7s1CZXO$W{{Bx zlQ2DD7b10jDOjSj<5l2uS45|I#zWwo=}Rc?Ncm#F*s}YYZiTHV@kJ_55Wq#z3!;Cm zt9Oshyh}G%Z7YqeOJkPz@VR)e%JguJ;q8LH&Ixs<3+Bua-P9EByfr;sn8(t~0&VWLtRgoh*x0nFF-cP+p&eT$c@4(^2q zr4w!!s%yM7&{u=0 zMe*Z8x@^E|L&>zD#{7>K#uZ0qKHV>{s8z!Jc1{ih$kL@{68YSy!H#x0*Bm2CmK@qU z9)6gQJYUCYe^Cj32HK2gj^+GJ)b_;zD{Ow`+Ps%K=ag@jC&R#&OtFHRY_9Yqm-Epj z`GzWcw85QBWOJm+lYG`VDA>MKy?IeCl`D=r4z)S{l{5Z$w4cAZr?UOmdTj*wvUd-1VC~>KlTREB%yf3CY~vANnY;XspeJai6gEPK)p>jJIsj^?yZ`-Xa*#aMi&duH$vpcK9bHFm_?F*a<6#fW*zIAERJ@)YJZ*cRvxxSJKh8qf zLy9F>eMapR?tw|Q^Uy8wMuxM2OAO5I4hw~HlZpr7-mA-@-o*&z*6mfzZbidhUV(D! zBhaPH+wJN;rL(q0K_S1TC%Hv{{8Ya`m$#UVRlM*CxNavqD{zP0FcZ2NSa7<}?IXx4 zoc7SM=CS(F+4O*|Wj7RrO}&*)j=}yT%$*A_s!_N7Sj^}F*)l;`QEr0Dyf?9HmhB!=a$?93YD-!ruTUQaIfKgrO9j7{{N zt(*jHt*ngyt`FRB`JTfS}Q5rueKl~79 zdP>f9eP^iPK0mWX0mGb|enB{g5fV~h8a}Y00WIrV7HMbZrH#S0bOVRWl!g5;^7 zvJmrqm}A&RB5RWt=SMX*y?}Dk?D4|%)gxILRE4t`+9+zHiVJD$iL~IptcfO*#YYnD zQku2?p{~Kp30XeLfRY)oj(wQVXle%~Ow{OsR-pdUp4$t#!oNu#<5& zG-<&}Q_SVYj+Vu6D=INL=@&t;O#RG>w0ahP#DWHVt0@s*SmXkY0!|1ELGeub8PZdA zFz9?gDaw80jC!=tb3;tPNthtEb{#12apag4O^kd9;KyQoE zH8ieWEil z1{pXVUBN|+|Iqh0@x2xxc&5Y%+F!tH1FAvav=FB~G=+P8UHpGNe2( zay<^^BPgkbT_9!PL0ItFq{{6gmC_tMY){iNT<7Ulg~Pkc5YVNhn^P$<*$B5}P>dc= zL0K_gVnSK7Lso5J7G_f#lA8*W7bRUIXh=(1S(%2*!Lf9tg{@@Q)OP?krQqI;t$GSi zTTHB5Fq470FvBVqSR7e&X{hwno5V8XO3-7)Q;Rd-7PsAA=#(q)snS_qpn8dT;~bxl zCJ?ZZmrWVtWXr{wT(g==w9k;$_~WolKZAb-JqKIz zI#vURFaLkh@=igb0Li*;+gNSewr$(CZQHhO+jjSA+qP|=nK^r(I5*V1l|H@=*G=p2GtNnspK(t!P>}F<@E&W!We!AETZ?`n8^RwuD>Axt1O_{IBsC4Lm zO-3qqG8sO%v&=*|Q$;4suB}V;36oA*OPgM%6A-JG2`#s&1LtX`Sjy0%Df3+@!`Xvy z#NIBOuQWS6F2N#fha_H{SuBZFq+DUi2&!sLCQ}VajJ28)Aw^yjC8kmTco?PIqUGkw zpPah{VMOcK zwi88Y^0G5j-6muD3Y-v9|k0hN3mVUNs`bVXP2TAN1Z?UMsyymZeJqrG_JZ88i&GGN)fLrK}zhIeE!mxj*q}W?_%sbw$)L0z1-nM;t4}Y zR-KL|C(5$UEG?y)lo@JVC~{nk$ad|{XhG^6{zaRtmDAOBEp0+bBQ@=OitM=dR^s6Lx`#uKj?A&SD5uw=qxIclO3QQ3&Xgw%MFfvc!DF}iP#frS;mYtX|@!wsLxQ- z0*y<=?FL&3cpXCsID+>mNYM#qTgjNtlGH@S31wefWkrSSqSHYwO4KEScPg1f>r?bd z+gNq%g{Db&Q&7uvplKFjw$gIy&rfp_?LmGKR%3-$I2FS(%YlMUTTi(#_#ZV|ITYgn zo(MR`ZO_#2Zq~HzRHjcN!md*ynyy66OH^z2jeAGVD1N*IB}5;X!LC|cVVmtFSS=^} z9UdXs%3M-1!_tC-GxXTVA*b+jpWm^ATx?@_p_24t^T;al#%pv31T7J6`9sI4R%)UG zEY~T2$-Mp)*m#{CKJs~J=~cA6D9l+ff8U>q?TY|y2uN) z24_IX^+#;r<+>6gaDfT+g?jCws1Y6LvGYaguHV9kXh19f4<;ZqOT{>Cf4*XF`|MLJaqul#G)BsU7nW1}b zjV5Yq^NP;w=Dn8U3}xx<;p2WLk`F}5LzJL%XXAeAr--MoV|pKv;?r@H^A4num=qSL z`uA1&tz31DUCLu73y5ZxTex%%Bo&6@57Bu&2AWd!Mg)|7x{6HpO-*grLVpy;7Nd^N zb`ozU>0Lw>Kk}?sI#I-L9HpTPlS!hgu)%{i2lzGJD}WWQrjBbkZ`M?eAAvW4s48+b z>Gc=HKm4zS;eAlq2~XBU2E)#DaP+@Oiyun+u!YhqvSyFA#DrZ&C{(*aFcSO(a1eiO zkyGV)RuhwS1(RUu3W$-1_2onw9(>xtCU)4*P8$6O;2kVBc$Z?_*^i+|?SqB+P&2r1 z&Qn9L4oE~qDo9Y)BRg}kotQUWu7hpJ0s``YoYTx2zio|svM%LJq?JYaj5M2NqQ^t@ zsq2CH>9~a0azuYt1)5^(IKamw1o=w7@u?IP4VIP zI?tYkHtIsa4Lt{$qyhS6${V51#!F2t8UyLCIbEqMxN?PmBN0z6XKC9etLi6dVJgb( z()`dM*Y20fv7#o#+aR<`j|l;XxJaQ?$Pk*SlcN#8!IfU3S-C*F{F~{rMoWK52zzTU zPzB4cIR6@33N9ZN+Yp<~(oePHJXWh?D?G#h?cXkScVbLWJByQUVid5e2EH@96U%;) zPoZ)YlmSS)FNV4*a$kLJM-?fkRmNT)hU6mqSmCJEpvN{bEKknu=z8$Beq`8DNP`wk#lmJtPtG zdQiTv3|hXzLROjIsJLA|Y(PBx>=T5+M0O8SDn8(c8}%xD7duvDx#g5FFa;uA#{nS| z8tD}i;kYWKa&!?p93y>U#fV7-@o3BkhS^YjdLWx9tWiQ*hKjTa>SmE(MVP? zmXHX&HqxpHCFxDjfnbGt)8Q#ST)VR#)RG_Gq_U8#DD|A9vlM_7ZD58<(YN+!T^bDq zRFf^W;1qc`iy}9J{+OLo8l34AsbSu#L#q9(k)Ce9L^>u`i=Q6neVfJuik4jOeA7%L9g|&Smdafq zoQ^L9t>!qJ_`akJ6D4oB3J|uBKfxWgnpV*fC;c_pgGLWBk81=)&7{?=k&CJ9;lri) zj9$_%eKjhMf=LX0)kYg?@%~j0J$a3iPoE{{7V*S*X(rMhd=vMqjwVkBzi>L14`4uB)V&@(4S6V zf$%{>h;59Mt~cB485~nj`8$?BZE|$N;q{NH^t(iZGaLf}H_|5fa;!urJD4Y*!`kfW zk435J?q2D)Xh_ck!!PlTPiQA>`Cg zn_>6i;4gN@Eq}A^P}|-DHDbH+z?w6y7VZA1#UDZscX7A5?Mgf|8vOA)YJ< z%kn92Hxv`DPnF_@p7*cF!bq1PR9~*$<`zIFq;nkk+2Oie<|BQfMZ;OSWlniTLV$Qrdr*VJK3kUm^9HP#7gI*6MAn@^u$HUIPYR^B-U7riTnLB(&5jyK5d1ahT zu?sugl<%Woh?Zuaj_&hX@a{-ZwWP;Lh0*+vLx_6~<$^`g@@>jY{WirDI9%kBZNh0w z)9F^+Gi6Iqu=(yJDLe$6W|GRs}#BJZ23fU2#f6 ztp#YFs;nw=Ji=-7R+YViRaNIlxhg$Q z;%&!HU@uolujFXXS_B7KIngwyi#_Hv%@Rl#v#mCEW| zP`+F%>Redfrb=n6s{!jImSR*|dPzzHE87(*YqX;n43aFAzs)$&SP@L$k)|Odexv;0 zyOQ3VvH=jX26WneL^mIuO| z5Qx37Zp(=~nD9F`$vmVEwWuU^P~*4ote;{f6T?K~uWY=F6OHxwA7=a~4^xP5aRnON z?#Cq)UqOlSAlk3$h~M|fY30-sy@~PP&HInnB@<6Y9p2qZ#vcL46Z|LVB@^Xh4<0Hc z6VreaXTjj!yh+9z{Ewn|$9I{1TZ9>-tL65B!&EXc+d_n2V@`-*zH&#~u zt%WMUk(;4^s3J{{@2d#@>Lq-5&q(Cyz1ciG9_@pL`F%|x{hWbF?1}kRmw4FrKT7Gp z<0~hASKxn0(l7F>C4PVZS5i^pq00Y=4KU5GiunEdpG$rJ2xk3{UIW^HbtE3j{Eyrd zj1iqcr-^H65oHcG2rB0w%P&I9F+k~q^P7VGy&Ag$i1#3h=KwH1@t@+3&j4lw517K?Kf#ahK>E7{YJ3C2Xa~gj z3Xs7Dn85~|(N-V&g4h|uHmAE2xKg)*krNci)FIK*^%%`5#5)PKCA=u_pGJ26coUY;ArWq>(lMW4G~ou>=UWTAM%&i)Yk;X zUB!#rQCtgWV!_qnbk89ouW2Na=m3`r}!>D{wTP|P6D_^QKxj)OrhfJ zAoO-9G6Q#gbpANN_rm_#68Jq~ZV@GOzQ{HB!9uwqCpn@qo}evP|JnjG1RuBsT+dkB z0wHHE9MLHbX}nURCyAr^x&?&~+#Y^D{#zB#gsO8T?hM}P(|IX?7qhke*$2uGY`6K- zcg+tVvorKvNxhSMT`+43 zKVptys-@t{uK-eV_B=|&w>iM|gVmRwHSzi#?Cgje%bL<_2))T>{ViY3HRc{Qr`^E0XdmTWS#3!HrMz32Pf5YGc#tX>wcN;3&AU5Va~PI*L- z=5MU|hS{!*G~fNxUu)iQa9aC3rq7Oo=#O3z0A{x?yu1gmP@1Ekils^Odx&tUY7x_y9ae4*+KO z!s1hDOI4d~?y5pn#R4ydyI?r0MYMEMlS)%=b|HT`*XtRFCl9~ z^YAX@e*J6u9>?Ad5;h6|z#ry+*E<*ck6vai46N{4%VqYO=lA;s-Ou8EZV+tHLjZ)k+yW_FZoC=JZ||h<8lotm z<&wz=wb9^CY={st2tu-Ld0(z@lA1=M)|sLA5^sv`H}&eC@4f_syMz}t=ZS9e_p*I` zjOCN{j~8Jh>Dm$wQRRXWv#+hASb4BpFGH9%+K^ zB*$C*G`(7R@5B)-8W|_LL;Dk^6-FbZyT+~9(yHzj0W1m0P@R)II2w2NBs~}Ma=G*8AeN=ZGeD<>j5pqf`l?zl_ zMf<#<731Z>bF`$^rqc%v2A*0f~%(0|`@(M*w`CblLXfi6W&-_@)@vOaeo{ zoAKf+@gsQl02AUnk?9?h#yb<#8>q-v<{!;V+hsE3Cy4oyV7Ug_aE{J8UZDta8N_i$ z*1sPZnm%cTFeZF*FFj$B3(2452Lgt4QpSsy|FWuj4UxK80|Nlm|68l-{~rQp{4aqk z=~y8NAoC;*4-dD*ESLKFfyE$fDI$P~Boqh!p;=pa9lyCYoiHZ7vex`)^8Ql*{{!$F z1JC5uihw1bA^d1dB&b}@*vHvpJ&?0nYB-xzB0XfN8%vM-) z42fqtIf9JiT0xeS0PXe4omyriE#!)-!e(Wsynt|SD-E1+Wx@D<#Xc{wFtn0?>}1_e z$4!0MnZMNjp4Fn1+zM<0#h4te9F^#Ju^KELRc`b7{!r5pLo4OP{vol5?EJ^A7f zJ6=I(6Krw=c0p_@f5#!@B(TZZw=;LKw-_7?WHpR6;dAX&O5W^1B%NY@TY1F`7+QyO z`9gH01|0>;nJZY?v)AIRkVN1$_nTaA|Alo8@AY`akJb2SYt9K|k3w(f3S?f~cg5a~ zb*8XZneT1)Yn^?FoqiNFJ|py zS0Gk!+zyLNt$-jK^ zMCCt)yvpe~K?JP3_wWKjJu@stj%%AuTXa=%Yp%6LnW7@x1Yy&#$cr!vVpI7$u&^_UOwJCyIZMCzWB-9v z+&_>im{Lin8;~Sd)UU5Bm(7dP=2Ec`^_`cJ1ohmW7x~_Sek>#&aK!yC>+3%uT#b)C z(*8|pY_L1^5WH0`ul12VU9_ic=kg+*U!h3y!RKqRfPDqosa^|$c)j;eBIS^fn>-F` z(x4wx-P?b+rH&+TH>Dm^nvXc^*+*iZTi|e%p75GDL=>(Xg%n-wY6|Jj(1|snd z5WO8o6Yi-~|D0+L7WF4`QNl-ep~45jrT&sA94I-%Y@e)7oCrk#{n z?8kZK?tc63zP|20F0bbK!1arEEQS#dv^X#!%Dj|bg=0vmTWm(BD|oHlupvc=b26-% zkr16ndkjydkEdIRWhw##&l`7hWX7;+%?nq~g4gNmP%fs8@p%$sG7&lWSc-Kv&R^wU z_d|6%5JF*Y(q&o|=_`yjD+Ohwci6GpJe0GMv^V$2gM7NPI&MY2W@yB0W)ZForVAAV zjORterGHLsHU_FN9aK3Lf`=AH2%xneVNzL`v_aZdq$AWwoj;g9ajUP(c(IfmnEt_~ zW|WVN*Pni8S9Jx)ch3qiOa|%DG}Na^g_MLWBIs-!f>he8D7RKRorKj6MB#2D%k!ez zpzQiqCn=wZ(mu_spNZC5S1z5ochFgxAeHVx6XsZXtJjqG@f~p+Zd{R1c81XoZE>a| z*}C*>rOIkZj81bwxfUxDninU`yozGaib+vw`%)(>&(6x0cx+$j8ssObL<0q_L>r2fiAZ!!*W`QLNOO!h!+GG(_B#pv1(YWe*lSC)OiEe; z8iF0r=O7-++pXy6EB5N_dM!m$v_cil^7By##35cwR|u=?Ff6b8WSDpEMy?}(E|lNJ zVuCrC|88PkQ11-6o~vC#y7HZ@o<%r(9v9&Px!!*=zcM#&TYlm^U9p`To4otMoS zqRx@12xN(U9s?ERB*UDKLl__lafh^YU1P0?!1M{{m=HWOtZaJt%3%CGh2^f|9AjkF zfZE_A$v~MygYi}Xq;UzDkx@+jrr%61BEWnsw6@Q%CMTB9L+-tIjcNZs{MkSnAx||zSLwWu9)*5iT z*EPj_&_bnz*m#Q=?W~BWHYK!KWr9`r^PW@FQ+N3-lX*`mGvMs z7w>U66dvu%0l8Y4KN3V>nyU$(WR7FB+?>tVdZF#)I?+m4fNW zrZN4cne3+SBEGGxqj-W@IRmdzd60L%$LCO+0$JIogC01@eX9k<%5=Nu$B@hV+bU#5-D02QJ%~D|K zos@(rX&=vQurV=M!U=@&@I!YIza@03LXM0Cl4(8dS}nmVga9kpW|Z%T#pEMv{79-( zk99uIDLDjcH71T&phL0sEm-aOnaNN8QeU$Hg|lQizN$o^L~BF3l{~O%r+C{=*(q!B z2vgt)C|Mr&b+Q#&Xn`ro8co{)P~3CFRA*sX*e7gWzzK|@uX)O#-&OP_y)yc_GMKeO zOd2JZRmgP`*R<73sljcHi!tM@zOz#mH}ht~QI!+sJoz$*cY73Srm?fw5L0~_cy=Nt z^h!lWZ3VlJ;R=!OmNR>OeT1$IyIED0Vh#0`rXVINDjd|hMP8)`!J}+ACb9p1XqtNWD~Dl1Ha#w#N#;@ z0uDbQIj^ZzW%(mh{r9tZMLR;h(5=<#CDiGn5zTt2140fB7BU2mt2b(@~TU8 zL5Uf1O-{=W!d2~abbiwcUm%v157C;MQr6H91NMc+(E$0*&K|568cGiKz&@r){!Zov zcI=V8Gt78yW(c%cf-N~5T9|DKtW$jl=0eq`HYzO1exe~GWEwf`KH>JsVJcl1*Wd_T99PxgNYNYYx3?LJUV&SZ>+-35>QGP7TMdFY|1EF&?sxo-PdPuU z-x}VBjvA}qS;BZD=pZ1C7XKvbTq9_+^^d)NqqTr7Xo~euxAo7QQ9)en!Ryk+VF91L zS{@9~acwT#cS4sZ>63=rbBDZaji^IrUqhzZL+uySDAXLxGbCGZPIQFo=wDh=A*>Yx zHiH-Xn~n1&I6>zJ4`5GwBEz*PKxYGpPkV6NL9Y3j&w9MuF+lJ1KXHfnyb(g|A#F-= zL*3nC_cDe(!MtBU-|oPvAoj|F?4*7Z)k(@UST z7$-an{(b#v80A8ZhDRPe9FLOwIfA{sq>_v;Z zs}C|b?j|a_omLud0B#E{U-c1oVvgP6CmiTrZ;ded2DH5rYd_mr`&q^Oy)n!kVDnY^ zOefIJm*v_Y;&p+4koZdGHp@?D@0@fVb4w<1T;TqQ4$xr@Rl%(N+Sa8ad<7Q#Ooo&w zpQ<4thKd6_H{<0Ql6Xh%KU&aCBZBXyjK+l!DhgkSTu{w;w1=B{(&iE5nEgFQ?(lY1 zrPXD@>C(m(NN63*tyG}!0NGKZG)kf5fXqfEA|o&p;`TI>kfn7X;Ehj`a%vp?evSWe zh;Zi{?t%CXE<3vOXt(0CQtOz7GSgT)`gE+LYYrUB1#mq zdRNX+ZqRJ*BJ>T(8P+&1J|RjbCQG{&F=V4O0v>P4||}8M;YV>5>l!qnMaX3ovzQqRg~B>VyrP7T%u38NGGLn z&m}pqqK4Nqvv>ouHGo7PZnMYU9fkA`6FKa1N2l9U@W#U%f=3tQTR5q7q~6b*93xkg zkrFSGa;;B5Nl@(4E;I6IiVf=5s5X4mtT!I8YFBPy*lC9u%rQRTe6i7wt`dDupJ@}> z)JW02DW6Y4CDX8QT2NLZo$i$HQ)CHk0(tlpGdYFut>C6tNOD@JWR;z)%{FJ7zhX20 zb8e_ODZ_E@>g`&;=tRQxy|FQ}9{C7V4$q`QePgKt^w@aKFs+U!s*H;W0DUelG z>^2ijc3S!~UDN$qQuHi0if1JMH6_fdvui#qkqj6OYH?yAA3{V183i3tM1Z3jOWZq{h*fdYYN zEY66NCRj7h$l+Q7exkCgv=vuney-)1mJ=hpt=N6`SgayY5JN-udaEkC;y5?6)5}fr z`&lX|J;~Hb6Lzb1pqB|~O%o#g!*3Bb)vhJi&MesZQVBzwNi*u20!xfU>JraU3Im0j z=x{kq1+Iemz+t7yUz`1dh}hmpNZ^+R#g6Q@S{HR96y!R@%{8s8lFodM<`WgmX|^cU zZ9-)Yn-qf_{Ss@`N)dO+rf3N^ITq*+o%B8dK-C0pY^xo;~u+c}yL|1**^v@|ht{zuB*!14c@q5NO}+fBPBTTQ4y=L27% z1?l=d2hb@jq$x>>Q5aBm$~GIQX}hLxR)+lw?MC1JLMset$wx~bz(2?wW|Sm=TtLUH z-%N3s&E!7%>`pz6-M(r8)DA2a&?{dK9@$PqOB-;wGW{vt8%WaEV2@pQ)`Z<;$?A0{ z_ukheq@Ucmpme)z^Y~j;a2kbRv0YUIK~-Er`pO~VQVw&D@{^tg=Z1B1(;15!IzYYw zWiz%lX?6ygcCCNJI8-C)<{qhRHR^g@KP*4vszu#4oS)j$Deg~T!Y{@hf&KwQ9B&$K zVj`$F;yU7O)k69O-hBcQ8W3sbU>5P&`m`yaqG+ssg{UMp5Yb{Qg3E$Asrn+N$BjNd zeU5I}?qSX>VQfFxFOh9{W)p5d0DU$0vL&9%0dyo1Q!CB^=lt8{ogz@B#3D(BtD9li z1*IaTB4o?cIhkd%p6BWV@iQ5EoSNudEP5;;$w*wKJJ~jjqeaNu+BaC797mwgf<+6j zgBmab3kB9=(&N|wnkMr`zCsej(w&HFTq6hx?@ z)ST8$@qnC}^gf7%{w{;9K_(}_7sHbbTy5kpO4OLd9x0G1L4s|k_9n58IUQx4D^nF> zW1LH%`xZU*xt%gOW1n-AMg6DrqdWYL-`0)oPkm zHzHZei9x7Z>^f8X3aa!zO7uP&^g87~vYl?Xq#4WmsaL8qwz_6{KCezWy!bx1ykAC+ zsQ^|El<2g9vWi62lx7FVlqV6=BA5I!V%)a#tt&})d{&%8AGF!6VREb?6n-7 zmF0vtpPP5GWJ_V_xPhSIE)G4}Yso@~xWM5sgDe6Fm13cSiN=@e4?p(edCiaBpxs{B zS0{9k%tjYR%O%PXj#-joM}`v8Gfw8dcGm0#<;;o?YdMCd6STkZmCGOr871pU;6E8Z{6k;4bccc~FvG zTj!H-BOHiYk;TCr(qOU9SKPO73uYtv>HWOiPB5UimmF)mCYcr2L!|84R6QF45vFy; zhbXI2$xUz8DeB!->2q3pDnJB+yUU4!zZ77f&GGFZ4LADcFPQ)H9@8y1UFk;oftulcFW(n2Zq zDjo6Pj-66>HP&H)EGz9DS@3* zDA(vF<2(3>n_O}o$cx5g=tLVit0AtiBuL;lIVrg^Ndg&laFQ4P%uizoO~R_&r7dbA zO9{siF?vB2)afPCm+mtRlgL(PQZ$tb+bSAJSi+MCYhyh+3=YqFA+g>Ii_{a^l zDO?UQaG#De0d3mB9Y_mZuO4C)(PW^rDK6Q-&K`nqacpNVw<$IZ*Y`($^~_cvTvAA` z#@!X7(Lpe8Da)_7u(09S#_39;A(~C~ypqoq}J}txS4bYU7;jR$dj3MAb zlFMSO&$D_1jdkLOvRS~*AgYbkJ3lWDReG@APsl9}W5U!Ox>Q!X@k>opS z4Q+Zux%5UIXpMf-o|Pk5Abh-#f$d9xhy*(fo$*yJoE)L{Acb);bE$k+JyGyouL;As zPt9$`yY4&tl#lMs-vn&PEozmoAky@YO>SzX7uBVHPg{IUR& zIuXpEn4MNUhE7P&?LbjjL!eosn=MIWPUe3+Xym`OVR!$ekKvmjdK3d9gNhfuWcJe1 zg*CqZhV*+mFj_f*8L%05&xUurlwME%A^bC?R4jgT$N}d;c`0M67&Q8lZY>yf0=7VY zs({Xk1c@6@u~0gId)ue$zJ!X4^tNyoD%C4+H$k#XVV+Z0>+|IZ?$Hz9s+fG=mhINH z1f#F8jf}eF6F$+Sr0$Fmbt#C}a1@xSIkF4o{?--U*OJ|e?MtgJGihkWm|6%Xujc50 zi*qy{YP51NxvXel0v>t6+kXH#_RMXfU9e@b0^G`#raZ+VOZzApx?mlKnJ`o8kjDSY zvBWA(gn!3?*>yp7KmA&NLz5hQQPwaXvW9ZS;X8R*Y-r~0d;g! z@>7*mfvTaIirHl)k~NdiaJy)3>8=UwGrSbl?SOz=dPzfjMM*;&dapN9Qt$)YME45q zxS20d%trcmkGn%qEN3g30^7bVTS#4(ZhCZg`%k9u6Y-^pCeM7ek6~Ln`w5~{%{K8z z(<(0#(vw%4H`6dZk5qA$GOaWHh3v}Fw{T04ob!Ez?L!~ZrNwUS4t6t+Y=uiXPElw) zMa29_StUZzbWMGOdR?Ki_K>94F6ObCF3c}HEt(lFHNbg*mSAU=`0Jl@UD3`sIqoU4 z7o>9{;m$Ax_$|_6Zt_j>IQ!P*YJSuTq&Bh*Z67cZLqW|-9Ct~js^leiucG}b4+P>-xgnUuqN-2GsHDW2WIF<)IMbWNMxfxJK4 za+EOLmGae1O>2S*vOl|qBonUN0Zx)kL9wQ-Txy%kO}TXPaw*D!=Shn1T48~(u6C~+ z_+}8#70m22Uz`a-#j^wtZf`x;$L%_(`&*>yELD)bGAN#}#E}@i^735%bDvaF%^xI1aT-X*viJ+tS|C9Sd2>N&Oyc^?31*Z6H4&+@5dNFApc zY)+K5TD#3XWQ74n%Q@nS44-5zSITNtuj{B zo2*g$FM1)QsCN;4ln{PHyUV#yxJRJyz_q{s8k+g5M~&PB2>>vR{_h%=g8yHOL??Lz zGn4;gno_c{LK67n+bZET{%pNi`TWfz7`@Q)Ceo}-&?+BJm;dy6V(Yo?z7E}%1@fDi zk53+n_XYSv?(hPm2@1LybZly7mg{qpv0k^!>j!8Lz6v}AX-!I;a(=9;n0=l=A~Dh1 z=rh5{F)>=f>Zm-&i(+ip*q8(#HbMN7Az9IZkWV>>ULKK{!C2wFfhB(hL=91WD)NEk zSYKzDh$N##S-s_x9Os4M!idv%WqJ8mo}hm3V}sR>spw{(V%scR#-@1_(S42+YA%K+ zz>-X^94^2J0cc53xgNV9Hk7~Q7&x_SV=n2wUTg$wC0!T}2 zZ*gmH0X0c)5c03;>n$c;yt|j+r~?my?4h+k6VNN%EYToGFc1sMqr`fx$HN;?+fP^w z{~I?R8pE|Y-Q2_g)yg+_L+d8#jANC|N4hqj9HI6IOF&6G{&9H{RxZ|9<;@puP!1=@ zvV>$UF|Q%W*!GuLw1Y@4Ly`IF9lk5035|yKNvoRsv=B39@8_54iTg4_qgz5vSNCgf zz0V_X;fok`50#N>cOCcrdR@bW>Tv5T?pVZvAEFgga@f~vL(7YoaGw2zTr`{a>n5Vn zwb&NSkk+X~fw4!!RL5|30HxbIRHjKUx!v(C*FV|vH3%@i0t5hf0{(Yw3H^s`(f>c4 z6^o_Y#I-h>Exvx>(Fj{$dcv1x)*|9j@)Uu+(yn%FL|GXoW(#w9B;=9sKLCEo?q*2B zQ$Y)~S2H2eVOfADAh;yR65DL7h3rZlCE>+9&A=0l{L1704X-6Znq)t1W@0Vm#-b)zKOuq@g)_3xGfLH!xn1nVj& ztEU*Zawlm4CWvgXdcPsgBRd9Re`3G)BpLNN= z;sItY6E+$#&h^~e`(KVC&=<2!Ip_>{W$PlEp%K$mCJ%E_T2GDgqY!6DR)Yikb(a~$ zts~Oly5`ctED5XeM$BG-ue@;4p0JZTOg zV^F6$BQcJB>pq~{Eve5-@BITrX8{h`mfLSdd~Lwm8%w)cu5Kr zjV)T2lzzOKa8Lq7-=t!YPYoJ5Za4J+N+q9io&x!L)^!P%APpUZ!6`ME3 zX)G`3tz`ABr^+=gB0VP-HFoT2pew>^Zs8V2Fohkt6I2tA!rEQ`1W*5KdJaIX_ zHrN;PE#|}g?cyR#$^;ga2jb)q`-Uhq>2eSyAFUBdQp&*y2#RG;7zzYBm4sj+bBxv- zqotlETlTGB2CcAa(48$ZZqoPMZ4?pSh_#=11`Zt@A`yb}Dt+;y3GtFS2sgWzeFEGL zb5N=HB!`ZIs~nF-h42=F*>0iKNw>8wFgf+a%Wk0siAAdurUTQq3{bhYY3v;g+5yqg zzJrC2MJmQ3a6?Ij&>?=nl&MCb0tlm3sy&8XgoC|0r?eITCYx&emKYp^2hidXkyiFJ zuiE($bKiBWt)G{Ypi~W-qm;CR+aI_*Rt_-h2-{Ru>Oq(7I+Uf;1H}*Tz1{t_Dh;%2 ztFM&maWRan*&{7Y!i5K5TjJrJp{MZVuX2=hl7VTC+nQyMXRo;>?qt`oDC|T)qky&psu)JWlQYn&4pi>3$gU1q=a~XYWv-Fy zgs5J0!_ua5+e}s3+LZRmEPhMb|O(J`g&<~%;NOhB_4Yx-!_m6KcChVI9f3ZgOe zZ@cG$A;7V2xQ`>j8kJmtNZ%vBQ8Py|OcsjMo2~mW4vgAEB5aSk;k!Bp%#eb{6*6-K zbuxi40mh2)6m>R%lHWe`DWvbZR8l0pBsZ^RX*2mWJ|i$2i+D!5oXkP7&TmR4V&ole z&S6WEk78!^_}h|nGx=5%YEAKdr}r-Plp&Vlb3N_h+E0mNwgEAT^3jv^f5)gr<@A*? z_q4hf_MezJ;RG`!r3SZ{H{uH1Fs0PM4;p0(vYVYT)gs5*C_dcWz=pobcvZlN3bL^$ zM6k}z!_5^$Y3B+vV(I;G#`eldqqe7RvcJ@mo6UbC*v$G&q}5Kf;<>QGT`V6QwDY1q z*t#M+(orWVG_UY`QAUX^oa;G~m9X0TiZqm%I@3A z@suXoolmcSTf`_WE%(R&74vg{-wc0e$%Hx{gmwO88~WCCe`h#)_q@wS;2azVuRiGF z7m43Mkh$Q7(y-)*!Wp809R^S8?TtM$3(%#tPgY%I(k>s9ie){hFg4O zm!#X{@kCH^1{gah@s_1Kl=4K`ofGhu3%g^&8Krx|6gh)vnY(1p+sO}k0xCJD(G(T4 z0A*R5jWfsT8OrUQ>`UG$x_;ta9PCmqfd5-U;hD%=e2VVmUwUq$3qK#dTc}r{)4Z=8 z1!ciydq|oyd)*yWRu)l2X+-Aga1}M)f89-XpLI;OHNb>wdh?6m)`+~HHU!@uC1bfqEYa)#}?l%&Tex>0|-~b148L?QWj;|adH^lJ%6-)2(1Lo2cP16+ECCg`fAk&J6 z8n}j{=QhUfI7yZRWfqPBqOt`YM*`Z*c5o~A&(n^Q3VhcG3;F2g zQBhY=G>5y$Eteg2s?+`uyva)mDlUNpLE0^D3w5>U*tnLG{7@qf41*sw@lCj!3MeDW zK*1+*IGtqM^*UwU^7VRy-hs&Bz(7<7A4x5XH_HiNyD+~KKZ|V_vcGUSv|&*6B`v^} z6ay{zvRJg0Ks{@%7b}hk=;qf`c`d}1Sbo@Hb|IsK3jsY!Y;Xr`Z6^S}_k_QYFaLP9 zhzx|u5Wy}J*@!Dp(i>|g(9$p#e5_;8FwIC76E;!aHG1RbpVI_*vp`ya0HN`)qq`;y zrH3IPgE*R4(W}NG_uRB%CHE%9q=SrJO5h*TWQe|aS5IxufvC<7lqv7eMGi>pRMN<@ zg#gV?Jo}M#dT#Wt5Sg&EqOIBw4Y&l1`1bH@4buR&NtB{0Ww8Ju9iM-kld8MgYwdaX z5!l6F^d^dG`YPex9PG?XVW42qp89N#5KH3X{x90zDY(~dTlbD_+qR97WW=^@jF=-D zN&c~I+qP}nw(aE1IrmyO->F((owLubdN2FcTfg4g)1Tg3YdggHRzbqjsQ9Hv5UFY?JU8Ha z8J(Pbd}5*oY!ahG@l;t<{hv)wZq_IK``4nx=B!TFOrZVVUxc`(b7V&$9WH~UT9JiI z1vHR>$ic~ADJJTkAmZ5Z(^b9ORr`7hSCJ1`cUn6EeCyFdwRwEy`hPk8(#??Hb zQB%KIs_^nV%*XMr2UkUOK7&RhxiPNr_P*?DW+!$~mAQTZ2V?In#LhG4BogFK#PrM9 zFjDwMz;OY=kG_U{P4$F(Oj<_}j=%<66tJ8uf+x10;(UeNBZP z{-N|!R&{X01x;H;!{5NN(P?@rVmc!=^YgfSTMvZFV6YF_@0EtzRwFb)L~n-^o%^7S zvP@2Bhb=&D5;4Uq3wq0%~i2b;I48voskJ(Qc zZ5cty_E#GL_qxEPLPf@*D$L4cbe~aXeu>soVo{8dpK;q&`3BiMjW1U<_Y~`OaF-rZ zizy++?4XOEGjo}eAecaG%}lZo%rN;|EV{(%(60L`;;CV|Vy^pSB^Vi#P81)fhMVzr z#&d52wXDG|l9wYm1AY0HlDxqhL$~&2^B}`7<&xGqIJupKz<7{)!YPS8wl0(tCw`wi zM`e)6e(0_I7^BP%@x&8{yyM>>Q>IK|tQcJwEgyP*DCQ1wKb9m2Pe={cJHNVFo18El zK~Ot&TsH2UX^YN;W`Kt5h4ye)K$5DZB8zKxKFH5}ovr1TVkiyJgF7Z0GN$ce==1d0h~wKR0jX60ChrrK_SgX+b%Y{ARn+N&8= z;bt)J$c6^m-jwwyvVhVsJ#Mkm&s6hFW?Za}eLn~Hzpw2U{iy9_{3vtn6sNUy`i7sX z5UX6tC*Q^kYFo@=qK)AcqJHp~cs2YL=*(Xxgn}+vL@#}?M>Py>>LyO=)&-3uoxMG5`2)G@E!NQaPvyB6hXjT1DYwZN zCfrxT3mi6`hf$sz^F)%#dQSFUJ=iy%{)PE#I{&=aH}N;?LG{ZWxY!d@6H8b4J&3$v zVHR>HV-en3W&rt_6e6EV{iH=gwHP!$jRpD7&MsTu42>);_+R)`z?Ml zaWRWHsgNNlt@VZ0|9Id4Qiy@wU`fe{(=&q=5Y+%wNBRw^n}tg*)+njve3xW^u^yMMk>(@KYRKW^Rk z@NFzPDK;}@e`()y1fbhK5KsqXMD2pfiOmL0VNK*}B6+zWbIA z_c`iKJ^5Ni4x755D@UmDaz*$8+LD-!R=Y-+ zyw93UA}qF|g5CoDV!>^ZN-!6^HaSQy_fjCwGL0a|!N8uXGf+7(H`yY6X3lDXx5516 zWX94RPPhC+l~4%rQi)I)QQZ{;tOmWnkZtY-!l6TycPk&3a3&y{=_b_uGlJTy7v5_S zugj2N8+1i^eWt7?(HY~|UnR*t3kn8&4m_?8jZx&5L5YXIB}^~QStsw&?BsTY(OGOp z%#KfP{e4D%@=GjnKSr(8K^+tCh7@R~vr`KcNtmT1JWdHKhdHA62d;3MS>zmEZa2^% zJM72F>p!k)DpDW+<6rp>`#<)1|8H(G_J12+*8euX*lgEj7vFp!Ban53!tx3Q=F|Wx z0I6>IfB9Z!|K)rAR4Yqy2b&ivZWtlALGbEh}xfpOj9Ab<4U8SMspg z!Tz#Z;riV8Dj>9PaRJ=vCO#agYc|b>GkGf3n8)kuBRPbMrW#z^=>wvq-Z!+8vV)O7 za_V#Xhjxr1%ko&PdR^VTb1NIl~lR^%tt&-y-% z>;qY5sdJVp6})OS_GSCbWt`*9p35>l72VfY@V}t~`}jk92n+;t^B-NW|0Yx%|2tHF zyQy7el{idd_Taf_^pA?#$V$j%p8~6$n-MlTvJ%`8>Fv^@0Vw@?f2AR}(sOjV(>B?%bYg4zz@|{m?DK zbEt&(OD!YJzV}5zwzx>om93btYAc^53UL5Ekb?kZYP7z)kq|N7LCHece zeiznnyM~_KgPYbwQ~g4QRrU>Q5}grL)`wBr^19@?@lil**Wv^@>rK8jQuk8Yg)4C; z>9EPm!z&^3q*)7^jqELM?$j4|6Nft?-@l-G`3ou}FI9jlDy>BwdOdzexJKCrroBVN zUBq&X_O+MrJ}tv%Ah8;9Xd{fVM*`;%)DpW+HCL4iJEwj8Ur<%3HxrR9F9#P;venDsAh3Cc((ITk5PgSaoiL4x#b*BR(pf6*iIlM5gu5zR0o_<6s@1 zA}bV>RzUl&NHy_Sq=GEeUCDI%oZ{Zj_`JPecLREM;O&d(F_ThC&2ov0)4_})qjo!Z zOE|6@2~OpxqdNT~#RARU`U?`&ROwmGbYU$-0ky?={KBn{_aRQqq$A!lL3yu{eOgJ? zod*2KTfcpYpJ9#PXK^^9zBKYl8$^DM61c6MQDMD_n*PU*N(A==CsX)5GYK8cM3YF5 zk~;2hR=kH2uj=1_1uExXd3WBbXF2i_jZA4hOVDqYziuqTgLx)LqFet7RA1rSnK}1t z@D+Q)fP0YWsBO`R@DkVs)jopd-&9QMi~F8m(_&yao~{}c4dtM$2vwdGn4%t}BtbQYeUMRcDt&}} zJ=pP?j#|>%cNjk0(f8Dc6k0QBk4GFtI)Fd2L(Ev|Af#D8#7gSD{R$x~Af@x`pZ+%J zeJhNT{44L6oQ&XQlZ=uAT(D^qKjEh26teEHjm|UWExZO>yO{=fNQh}879BRgNF|c( zThDH#5}nYOUn(3nTsF$?L{$^B|7n!V<_N5P`2XwA|2LuH`ZrYTw(~!b_}7bEtYp$L zsGdE^gkzXc7!|2^QIr4)Bn5e0b{D1fBdd)a>1v;JWJn>90)L`~CwP#B4}cf6>fDYd zCQ{emhNtbef%%3ufnY(_sRxx1BO|FtRSl^rETb<&?)Vt)B#WGN5}bdKp8{+)Sodoe zO1&vrtz1DCz^+nR-tldsb!37IG9#ad|mSVO%yi(w6mA&0Z>(4xHs79#CAUbF(JRa!C4EYQS$?$h6zAwOEoDNKcV$K=gE<)4BH4{{H3pIqW_%blB~ZB6E&n(ei7ViU;lAC(XF ztgBzr0W4rB9~O294+ZJ z8G@gueM2qSJ{k=y{kDNzhSW9AYOZ2yK6hAsyNKR2UMoB*>TWg$FmUKZ={%kBanXGc zj?L+&Umv<2pC|$P4!ev9w`hJRYIy0&-Ppm&RXbLy`;9b5JhnHQ#@*>H%7fuFw1VCL z99vLs$q4rUr;{J||ArLG-$=QQk)sexU=6?qmgxwG)3idBmR#d{p3ynF(q9*;3cx~x z?fD_@h=i*yS*WAu-rfn4#*J+LsO0Dm3$&_m@Q zU*@!g>NG}b4tll3JV>Ne`CZOzVGHW7NM${C;a0=%ii{uY%CYvBq$>VLQYljZeUaEi z=s5Rspqb4){g|V=miz}iR+&4q}%%WhAgUe3))Uz&wRW( z@*c|>2z+YIU=!i(FM1W|*Szm~6u+Y`>_q5GD#5fw!P9>%$Cnyvj=@ctOKFFJ9$ZkPskTJ|Du zP-&!2T)jqX_t@TN?9N~QTKn2Z_@0*GW02Sg%&2-#BmG5|yTch=y&R`nm3i4AU>fJW za^Dr5v8>`>=`RjNO7i$GtZx4!RzLn*Sp5qsZD=o*#YMqmvpCMw4KN7_A{!F05n&W4 zPY?+xqFypO=w3jZ3=89Ez~}@QYzTd0_+nGjQj=98!%|ZTJw_opt3g>|W8>hG)w7oN zugyl6>TK0=uj7qpGnP~t3gTPwqptQ0&*|?Crz!s9u456x4NpNJI%G&TB&bD(&biam z8wi?5x#nHilf*Vwd!m{A_RT~Ax03Z6mA8-I$ydw#nZI-Drq9l$p-o7uL%ahpnE_$$`cdB%%HzO1QIDC-0g)iSQ!q#@T12 z48I?yI`Oy0wIQHF^mufuD7?Sl6qrsPi6#hK1t*bz#>%3(=xzH^g^IXg_gV}R+zqbj zZhdB1h`v4QtqoYP8#nGU`&%Q=g-L56+qmc@U;SaDieti^5>1&gaDOOLunWGjV@9WM z?p;51Zsz%fSgsV)t{H|Rif|B2;72CHz4vD-Z!y%MEj46deHJf=npch}j1}12K74$( z-7H6HG6(4+fqqrk`9q^o){6p2bGT>+m?{XNaDYULHE&}t=(=hM*%EVz1V-nmQZ1I) zW6L!+x96!xvUOyIe9mLM;AdXCZCO6f(|^S4*nFSt61liCoEr>>&0n-oksp z&9Vi&4i+W0WM*AS)z=o8Sj6K`iIiaB=O+g~00~+sr0?{}OmaYLaQFeq)(fe!myia? z=`17QTGFmP{K20RN0QZptO)qM)I<+O$UvZWo}N0Imdg}`gf!hnkk6{1xjnAMo{;C` z7S|M~c9bt9Ov)BZ^4q&j+){@Be3S!v-4HU>{Rg7hb1DRSGpj0kgT%^clMyV}b1c09 zuczsj7Dp1XbgZS=pyZLc6hbapXtxB7YToqCxnE2=9C~mEqrn(okYFUp>9&#C#qU2x=ouvWgz9<_h2Tec58^*+h&YXT=8tYw8Mo&bd!^yvSIYNgr88f!|nsOrzWLpmD9%p zJ2{=76#z#)vf}ybczy*7lm&jFxVxg=Unxx!$M8su?Bvu#?*2a2?L)xJy^lCvz`GmB z#ql?yFDSc(OR_)Z$Oc6)LteoN@`}3sI;SEJX2klLJ)q#b;sChK_kTFiD)_eTT5uNf zL2do>WZt;RcFPTlz3&0P&pWOZswsOW^^xjCB31o9SU=7X23|Jzc ze4{|4df;sipCv{>Mi&VsUWngELkCXGHc#h1E5&+Fc37{V9wechj={u)ghYv|t^t5} zd&WxxqP761pgr6UzloD*2?T0v_QI<_J}ueAUtEP76I`ie2Eo}eB64RCo@g}l+G@^a ztC+VBh!QW@9~)pZc`^)wtJE7~#=gY6$#hWI3g*oY;L|q2!Ba+)gEoHMNjFR%LH#}6 za{ZGcZtl;J3$KDOpcUq=f;79$UR$QhjNA=+%Ev5{ zx$Vubo$qjQIiOhp61@*g=;@yNqBH~?znT^<(G9)sE$kUcWU8ku@f9wPC%R(po*gHO z07l6d%#ZXaT-TR?VFk0;xIw^fSg$(LQWT^3KGq{Ubag*&0dfQH67lpzLd2d-sAwfS z->ffL2l%)6iAA1Y!SYxi1}0@VV9)XF4Gbmi&h&+`e4ZCdb<`w2tfe54f5j7pqUUGU zi8nN1i9(bJwiOYr=s^f+a7v|1dp>kH=sc6I2yR~zv-A=Q$tx8nHpHM33abLE@!JWH zESj&A40kgZbA=@#$_Wz6L;@4EBe%*M<9CPr8ekR0X@%#qK=zSKHwmQeQO-&Rm)g^BAc=A;Rt^=w-$MH`CKY z+!=BGJTBoW4e+y<4u^1p26AdJbz&PNbWlUMD}@nOV=RFc>=F1WE^XouFSc-Q3oS08 zn>3z=m7_XwEefV0hWrNmc@qA@<4o3h6)=H%(SZXO&!FYv3zzO$&mcwdI2pq*x*5{a z#Uo^Db)AY=s$>MWN^PChggX4$(xe}4Z4kN}dmlL|e)@jfxRM<5veZZr9s(kDN+-TG zdDU^eFG?*68&BqyR`cwoq4nVwJPN0yonG{^osN*Xf{tKtP4w+FbeL9+-X2EBpS~Zg zb|LMzXE@XcxO16EV+i;$WLK7^6gcD@%&4gOqtXv3k-W{48wAU(%&w(FnUg5mEv(BI z8^~^{Lz|T-ZVt_f=$8-h&W(~b(dn)t7jjX&f@HTOQNb`gommX|ya$|&ODgUXvH75k zLd8J|lhXuWX+0f;F)MzVWO|g8R%Y?oikO8ku#*|#flgp9p}H%w5lY)fE3Q>;aedR$ zaq5E%7Ce?P1Zw*~K%cEzC`HdOaOq|zhmne#)C6*JDMi0(9SE(_p5l~@81*Q2tsaWo z=r#+bT(-c-gJMv9tZEo!;toRt;6uS3TL(bh!ABSN;c;{!^S;P?h8;g^9>SDebW?Yo z;xZlPIAFjFSMsGVmuFx*o|NgTP0bAP}HBk3Gj0t^!6>>IH4sMbYZ&fG}6!yGD@U?&tJTV z8gW_bE#?lXgHh|2@8CKXdG$nb5}_62T|c%31Tjkab4q@|6#H;zyeaC3@9x7X^lJ~f zJ+%}W>;C74nq^EEm zVrF+Q!e6sgBqNDTQYt#Q)7mC8#W(NCDNQ0blN{9VKU0O{PZ9vUaJJY5m>J!6kTXVg zw&-{9j_$Df{E=JPw)0kQgZp)BDD17GmTT<1HmdA*9OBneQOuZ{pQFS&Uk79Gec7ZY zk7jYU1O?>Od2R&a=d&eJrZNPWaO8MTshaku#Yd^5mu@ik_ni|#3E8;4C4`Bc-mH1( z#Sa$pubcPn#OBb$6>%zd^P#MV;@jvPcStXgeWHCAZV)9AMui{&1A@ERtMh51kO zvKjkG7b|xU^>@AMsB7v+iVM6x{xO4c&>KwGl;0OF6lOH72>z{YWPbX$gcs~9k65Ry zn%_>(suIV=Y8=x-+C?|YcCXu{cXL(8XhJ--Ze2_-@aGHR<4|y)o}N!HRQYmSMpw>n zPuoEpuTSo_Mx>b;08utu895sts;8)(*rMhRCbp7=KO1Re(ee4zn~9w-0Mu|X#V!=j zUO{3GB9{N@9maJ2G9e%g+We9xzcd#*%?N^7GE67dd}#Kp(&mh7&CB5&iJK(b5RC{A z`dU`FAV!^IE*~ zswk-B^j}H9A#tUA?}U zMH=~0I107YtLQ11Ks1~$k;Ud?tq-HgAQj~zUcJitqB*f2FkiS*9`+bX_nt{@I{b&f zs<$j^;<`}n&#*$Tsaub>NM-iNyZ0OohCvt~x1ntaxCZr5RV9^sgm~8c`CR2_Zx3TR zOHAvaaEA)@%Oi{P!457vK(tiF?CkO#nFACH?s;K}F$aqd7@dU9%HsKw=7M5A)F zb@zh>6Vlfp0C|TOfh9y|VyM^q9%qz1{+^0(jMs4^u3g492425X>%C9c}a901g zzy4EM!PeCU89W>sy^&LwM%Z8k>6(P3k#4F9?@4A4S#iN!sBmN6iPBMp$X3WpTEm zD`3r}CP^*~QneRHdR_NASD|p~5)SMECrSAt$T2M@3Z$BzNpojk}-5TswhqcLyCUS)QYc>9K}`%0B%++IwEgcqfn`ifPRFg z@w0@r#IE_5%c(;NT>qX(4YS)Tw8m;mdy-H3o1rc)!+<0Gr+~(GQc`ts@U=_-cb zyHQW#oH75GRdFrH*?1u0>{9VO9gq|8C7f(lt|CiG@9#%D{Lve@NzxW% z2~Hb(2j}6MB(fr8L#AhxIC+t(c+1{z}(@A$1K1& zQW@*jAIm^&Ngq^ z3Ok6kjPx_mO*A6bcC=nHxJA~^*@EEIPfQJ8_$~)rewkV#zpz+d$^JraNo{27M6{)D zD17W)UbwD2tZ3Oj3tnHRutX)brwnZ;jA}?c_7MaTf8Vi1`PyXLOHm~_jx$FTDIk1X zZ{e}T|GCq37SR{6p!{*4f8gVBl$BD)I)Nw?&A6 zO{Bm@h`>dJfR08PAgp~{erM1MbH)_bSYGgH&T;FkqL1!EWcyF7YalZdb2}4l#QXSl zDD_FZ2``X(%$+wtE-c`{N>ORBCTIyT^oi@UabWKl=<>I#P?Nf_;EqG%G5PnY$l+OX}4WCVflflQ1nm8>X(LjU$5|`NI6c#jCIApWP!Lw;=q2 zqZgP>65oYPI9PrfDk#DWjTj$Xi~2l#gOfK&2Isa{9J)lz(J%7>=ab|Wz4L691bUj^ zYNKLHDcast>6ORtpMBkbE)~7+;^EGpPT(_I;iai+dmtsaHSy*_6`_Afb2?Y4lN5NH zUig7Dw7%yxi)REq1I*okJg+FsY}OAm5pZwMk`et{0}q=ZAtftj1bO934y7Uwr&UsH zoge|$%`OAI%f#%+g?Jqzlr!dLjD+yKj~sO4joN1j+qX*v=pQ9QLjhQV8S)6F2q7II z0b0RwLx?7DK>9^Zq+UILcEB#Gqdcl{68)nj#Y) z{1M-LQPb6#-2L9_5$Sk4-<9Lwt0ny^7h&2SVm61^Np_P#&PCz7D=LAnPWWq`br zks@Gm%S=Gr0?W*US&>9$lzLA@{&+JfK< z;qv0N64I@ZW0qd7odaWloaw)eWCu%aY>inDy&y^hhJG!Q2?5C-D-uj{T!`^Kjr@Ho zWy!6DJYAQ!+(wqs4#&H?ghzYx0;C1 z7yfvszXs12)cO{AK5G!84Va^`l~Y-BZ+-Rlp1x4Wdf#4VXia5_PDRz`-5q{KRRBq4WHyG{@?x{2ee1Z+SDFlqAxIX{pz_G`T_JWJZwrA z%RzR+ko@hp^iVtNQZ~FYGD$0JV`!6JOu>%Qtb}xh?2}&h$Tl^1y;@4-7O=8vWnz680fRX~b69PW4%W?{O>>KZDSq)@4ud)Wor4Z69<|20Y0^z6TE@Q1hNay^s^V+KLQ|cttkm>w603CsF1rPj$#Z1>nQ>;(}Nl zrPjH<)n8*QEJ?o?a4;|tDq_d=vO01o<_zmb{MLVwXTqmi)UD16832>h22A3 zMGlBUFAKgHP07HGc&Y=$J&7kW^3`;SJ2^Z_J0%o(lF@nx zvaSNMWb(L-C{k!La%hUU4MK9_%B^CbXV^O7x_i2eB4?zN6y|aD3dbtdB&|cE@{U!S zXpKXM@{Va5LbmbmfBJ#U$KKTYU;zOo3I4wwFfVCq>1=6eWBJ?E@!tdH&(+b6vA;X( z>nA{r7uc~Zi7511N5zaI{5cQuG&JDDH5QWK#)0zNS!-BfdpBeno;f-TIOiL1JZmLo z(~ByF*A6m#&bawMXQnTMpN#Jr4+@gEd0FXbD=23ir=~iR&9la@Kl!KMZ;E}p-v#~* z-&8?}8f=H8GF=!B%ch)0uKpES`=v#>0Q zvK9-WbL|}r!RQxdW~7cB{+b?3bMs#0xcJRYdYMUAfqsfiwQlF|TY*SPU63fJiI>z2 zoP=r_Sv0lhj9{E2{`I0J^_(+^wdhC3uq19OFsb>dM@z}?{Uq9%wR^$f1sVlo^dkJD zlGtf9?n^ZT_&uB@7&f1d$fgE!S?sL%`C5c$Se1xWy%HrNMfGktPFNbP!ox=%f*uG6 zc~Mxo!j{P$HzmVc%?v{JxxwI=6TJs$RTwYf;eZn45@*;h1-j4pX)lyPFpD~C?3;eWWVW_t@)L^-3vh;Ef!{oW*S+tG5m3vSUl=CYl|l`%;PX* zSBPt-?87_cJh;aRP*>^(@@H}*45P_GN|&%uKw=Co7iwXnq4{daS~!}Q8}8YZ)p-hr zT`pp6E111{!3m94#wV-=XV=%0E+pVHFV1CLp49We-`SbuT`Nw0y5IrbxA)OY`CYn5 zlWMgo2_p3y`mJ=3GUFK*J-brK56<*HZe8Vj|N6|tpQ~rEJSypVLrI$+8B=0skq-kR z`7If3!mUX%y@CnND&2<;ozSpcP8y0TWJc(a5n;K~pxEdBnd-Qdc$aaU)zsmT z+LS%Z3@FC3OKB3x=ceRkYgEp0Ds(X@)!uyEoExf%a)!ojH!^rqMF+A#0J3O`te~bP z;3o)1Kd{L@<$29$KrQsPSPI|MPsq%)CSW*?e3vLrQk>gIN~DDW6^W;eMOz8tvm zNQ#2tN?Bm)y|`=UySHSV#Vt8?bkyvhj|DwdH}hEbOTKK`@U~l!8wv zAFnK9qI6(65z~9s!n!Gs@T84e954eGwdw71)sURhBo@scrQX7AoXkCz(=uZz$Zx9TyAMxs=X>$3iakE> z+~t%TUa-*;#*-J4u7UP2DzeE_Q7{1(R)Zs*Ep(7e^3%pU+$UO|uCQcqjwx0_e%m5O zxY6k#4b>pH=RSq4MBSOwZ^3n`qin#%IZqccYH5ZcByZhQciz7C3&*+XiS{f%*)^nJ z=Q!=GbaKJu^_Vda)uqnjZCOJ-Lj$YtESOkBsmFw|oY?@Ptk0JS{<29UP4mXhSjeu6 zD;=y(>O^`~$I7u}-mdsWdLdR+O{UY(#%spqO)>Ka;L&l$*|>!|hfH#VGo|lRfR@%C zR4{q+nBLF)D)T4xsaUD8#s~0bI#%=C1$(`7&H{5{$;oD2d7Gd9$qV_`QRcBsO4Bw; z{6^UU__+}hH#661OVy!UuYaQ8nPwK=@DZ_*2{6pWBnlmEC{lG#Sc1M|J6)-btYZEK zUFRU_fg9MJ{C-F!Pd1J@bk}MM(V9JEt-eD}jig^U{6bEgJU`NoC;B$XGrGW4enX#| z7e={VepzwuEkfC0zN?Tj9!)l)vJWb|O|KT;nYAvV7q-=6%TvvD0ZIFY!Z)rn_n2F` zf_beahD+z|5m|8bl#yHb8kTRKCBi$2MFim*GQwKfqWuCvs)#ulY?O`g#J7GKUc2Rk zgGz1cZzy>K-X|l!ZF~-9oddg1i7WFFvN|a;wqA@nG<>ItDSjBTcgLm1ulhro&Lf! zPH#vi)DEv6tC#iZZEj@3)Ip06KEgB45je4rXyy7E^WDv#EF0bK(Vs{5->aS%+iv6} zR;>?T=iib`RLifvDn#FWglHw9dI3{6Ay0)s2O)@eqQWq)u8CX{F9^3@h^Q$XYA!Ah<*Lqf!(_-RY-k{DTC(RVLMI&u#djP3|MlrXOE2J&cmL z7Qp})^#L88ybJIip41TN9H!7c|21K0_4a1hZJW!kuSNY+w=2)oR5(VPSL3br>nZ+qw=U1A z&f%};xpJVQeL)@=HXVW{VKW;MKJ+@C{MeskFq&po+E)4KkwGZ4TU8Qt2@+bInv%3j zmW9I7l^WN=^BgWOY!O=~w#*`mtV`%xO@{G{mey2K1Ioy}DAATPT5M=P`*6mz>d)0y zMkOlBB?D{+C*T#seXa4)!c+N|#(qJEBQ$2Mk*3q)>#yl>Tj3G&B&9d~BDeJZY2Hyh z91%FE2`^im%f>kYu4!n6po1JLdeMsGx|o3_HN5)jnU`nSqOo4p+e}2zB&87I2%4{$ zn_E-V)QN>NgndIwlrII!6K2A;^@CZ;#5v1P$^6O-l$5y)EZ#mh3Kqh2`F5s9v?V1q zydcdJ<%z>IHy zg$nPQE&tMtg=G7xV0sHn(lW&*XbGYTDO9zskAt^8ISsl{aTp!PECW8>IVPiin#Tfu zoIix04k>&VP!2Z{+^h3+(DJ(xy*@5>sx(f>u>d=~MLo5*Nd`E@o9Fa?MKO-sccQH| zkll34o@z#MUC*Ce!)OP`u&{f)PP=dKT4`1DKBb8Py04*KyvFI>Sl5oOCthS)OB~AA*ooK{<;uz}xWf0o^<;5)KC+ z0Z;m%R&GZBh^vcl-c%!C#XL+i9^!43YB~I<5_;%YV0h094dYsD?aE10kPFIGWt>$~ zQ)CF7|GJ;)5q3`;sf0?~Y(D82jSI#egb_&b6$A-6x1j-RT!yq(XvwPNGR9GyZLb(> zYv0-i?F~CT`?aECxB;SHB%5-etUR)<8S1STs(dN>I-Jcgf_Xk2sbz5nu*J9LqYQPFruMJGN-)Cy03LxVLm9Oqax-mRwYeUV7XaSugvr>R4uLahnzl*(B})x1 zB5xsg`>Gc^{Zx?GLXWX~2DQB8FFavnbsre{vzG@V^P}N?#qkL27q~2v?Ba^ z;aqw9(g9P>chP?NFD%$(0x7N;J`wn2n|o8r{mfpn!|J791HSNH_}d0rfQDB}emC{7 z`fZk*q?q=fXP-bJI97?@eU~gWR4Uamosl znRBU1av1kB&*j?XvbI%+tkI;_DZAnpg z9kFiC8_14vD#{PMG)U&|iZ>Ag44~>dt zR!G{t&QUpQ#h+81g`k%nVG^tyu7+Dwpj0v85aQsDlL~fvEDP!4u8#~Z#~!mgo_OTq z#&FrDe<7EGr^45dy!lFUNz5oBM{ zJ;Mr=hYdgeg>;$X6bwH|-jHRw7qHm*qZB$54VCig*ufMB)<1qT1Xg80DDlsz$WNWW zBtKIVQZ_tITWD0Pj5D#$r5L8t7bev+M*CG^i`G&!tlG8zZh6a4k}=W?VSB+iay)RgFm7ciDpOK*rBz2@neh zeRzhxVkxFWA}uuf?zP1?>{3+vFB{$-eU({#9n0=eoCmOs&uCXS4LX^O9dpVptfU=j zt;*}7fbl+|I+n=vxs?R54!T3Hr!n_%)~&Q5`i}`tCy}UBg(0|W0D*wq2xiypyf{Ii z?k?{}8B6Vzi$(h`rs#u6v||wtI$FYVG><%1bwau)R_7L3#mc zM8o5=wl{%|dX=UJ?@xE4Ncl2Doah#1`GQ+#oNTA=uAL+yh803S0C)Mj{U1@qnHb1uc^{8PVyQT+Mggmm6HX5@Xs>AHOuD;Yfcv6wy?S9m))B zo;a0@alYN=t$l2|hdKq)xC+9Ezeu<4%>39`b5bF`Wa8gw$sQh$6iBsv@El%`Ue+5( z$H95zFDYNpA5dq*6H_)O(!iG3Pxn{G*-kPWok&)J!14A}pgHdmE*!F?@UWk?je!^T*)F8%_MDGaj zjqT4HXKY4Nx^sEp$nR-pB_J3?`+L-u>7Bw&{MToRd1O|k@KzO_)OHIx^=es+BY2?m zgWM3onPQjg{8#M!Z@RF%f+A9#h))8 zfFKU)vY?D(j(VSs=Ju>X^gmHxjLvLbf2&Zf4`3XXQJmL~tU?JAXJ?NFJKyyfO? zBtQcd)`Z8!$Nd@-Z-8w}V-%>UlwM-|9d{2debaQjkr6OFSKa?j(M#4UX$^I)8Jz+AY14lw-?` z4L2!AZ6An674HSf{&A{-i{Fi;QA+3x9wv*c08Xn>-Y24I&{+xJDJ{nDNT|w4=BKs( zMsq<^Jpah15dq1A;y(Yy_=^K<=?yI#z_v$qFHqWynQn{cr4{ATLO;`z79?kb->lc4 zNyAY~UNeZ2=E|l-k#gAKESKpN$b;Ffg>G9}Hp!LBo}6{8gbSjVlV2NYk+g|-!vPLb z`TPAY{K~AUR>r;e^wu=lF{9_Jn;U$L15T?H!xcVLc2jDYVybwV#~ZvodE9D&ugNor^)L9 zwXu5TrQ^@`$W6M(6k7K0^_KL+PR?Y91m=5FgZdrDA(qxAbV zkmp+isizoKG?r^*&(qrrQ@nTIe<~|T-SC(1fq{U2{Kt`H|L1L@|IOO}XKA7Vk<`%rM`qxnmNnZjuk-YPJsdwo z6f4{{oqs5*1k(jI4EwmWQLa`IOJu{Nl1A$iP^!EX0J*KmXvj3d(};OpDT1R*VTN{Y=@2%(Y!DV zo6szMotsXq+B=73K`A)X!Znda(6bh*^ozG&`d65@op9zaEzF!BH!$lG%#thXE>1!3 za(HFp?!qaGT7a_`M*h8B?wFpzadpOmTI6V*E1&SMo|n^KFjg(L^Sv?s&N@|B^mZM( zx}$9nNYKDe`RP8Zr);VTxy1hFoS`RaLy<@d9nTBg-{?%wqT;(n@6r6F=3XFdmAcO2 zT#AgdyjNEl1GI@|H^vrmiq&%av*Yk#H5X1O{?_GzGRqY?C=gK3zYS{mzphK>|L)Dq zWUaBWZr;8DHU?AQk2IjF?hcE4Hz>YI+&VBb;cmQ~DtV-Ue*gBL`H5zzVAFv@7%nF| zy?_}GbKlR;XZ$|n&1&O+Y~&gKe+N?@#TX@AFTqP*aITt`$YfzYhQKgGx4-(yw9|BN zsw!<%ZB-VM+s|UG-8i}K8{@>^(SIkE4Od^WE@ggEfueoScf1nUY2laNDvfH&kGjtU z*~nhYyC#HQaKMXpxUfKNGotuE|;CQHewBcPqW4*YBQJvByeM6pf|bsywu(umMNSOI8MUs`eU z3$E?646%3Q&V5F}`WkngL=aL(J^f?NRJU(Fztc(v;B)-7X3B1s|1WDMZ@3cq;UBes z|F?#x|7)sP{vB0g()~(W8!ACdsVP13F0q;M4rXiVHfOUaXptDce*99rjnDzdf<&;L zfSMhylgvhbAD>?cd7-1uQ_$AMXwocA^d%ydn~E|E+3m;{_$M7xN#PFx+lqqZM3{te zR4+xTo>G>X&7RInU^zdDKeDgoyk#g%x*`!JmG_g`c*>{v&_N=7igZ4}Q}L&iUdTvn zs0%++`sB>n%SuNU!s&f<|AQ#Ae~4 zv1=fvn7yo-e|ZT$)<<9yIKj4765Ob8xjMwo;*4&M7E5H$>`AN-y>#FF{#2LW0`9nZ;oHlT;g^ZDU|14!PXHwN7Q>OV&^ zC-X!|cGTm>uQ=39%A|8LoYJA2pg7(Ur8~-dw3imOXm+ZL%kKKqHSC;SFO510jdZ?- zv6AU&HfBz2DihURicd7>+OPHVI_I)1q%cp|!Ctx?2YR^CDqL**wfoW!prmAK481`) zSHaM_2=%QCV0-BH5Gvh?{T;xJXifZ7PpdLlI--RoZ(v>%v(86g_oPyc{RSPF1mnaL z=v&`K=#*0$E~`_1(9pNS>n+k25h5T=ehIkB=~GgTzxm+TM*cyt)*x{z0Pe#6HRSs# zmm^W)vO~JgZQ3AwPm(Ft7T5_=UG(j&-0tBn@*kuc{}U1(}v132{5 zX10u7YxDoc67au*egX%4VL3dbfK5XN<859|u{6$3@pisEot!WL1n&krMdqq6}@Y5YNymOxz)>g88j~=`$zXyw3ke2QFml4 zW$6%2VXLyHTf-lvD%1IZPQ98{df{TRp{)Ka>2on>uLz|8X~s|dqf|5hp;VlN|DjY8 z8fP@Jp+_6QYsOq-k_OFoDCxNpl>z*~R))O()#==pFK%5&@lq`J#^8VFdcXfxa%Xtu zl}Ej3QyMk(kJfw-vqy*b50T+KUgz@U2MKC281+Gu6E0 z5l_|Pw4wugo~C;I`f!2EaT8h}=u7htRo8z5R95B3>b%Wz&3>ajuNIqsAEM4n9?k;x6Z8 zwhdcFKiD4VHUBT63U2t+{k!zN{LfPLuLPB5H5&k`Dw>ZRO2_mwOtFHO6*7|m)C7ti z2%8P~dcizeg+--Wux-MI)5ewU=9a+Qaa3V}&#nHcIbJjaAs+t+|0ib5L3^ha>ZMHa zG-G;p_sb?=#yjUEr<=m}^VfwP5dF8gxNkBm#fIFfs~jfNEg3zmMQ1xN>cuv=vYpFy zc!g)<=x36pP7yX~s=1V$AXtCH>?9w`~4BS{6~ZR@B7GX7^* zz2?if%weQS&O-FsU;OFjOIdHHZVJI9_+hL2=N1;OF)2 zt)_LFoUY)41G1N>4l&yEh~zGF4Wqq2gs#O~&d+KI-TAxH+X?~X1N<}h%nkXfxRWC@ z1r(?JfLffX;qE*I)dtF2`t1vqaV*2PaMkfAHKaC#o6aCaHZK9rj>ghH@wRCh z?Axe9EqFpV>Q1!fmj=J`xKiW8H^77zYMJm&!!h&_r1Lq`29#kgx^B73{y~dZ@lBJ? z-uJQ0MU)L{e@*RNwoHcy+!)5j*tLdE?o>SoZ9UoTx}?Q?aW?MCiKvZ>DCI`o+(~OS zh)P@CUE^Crgk@d}2D|1BU>ZExT!S$2fYAvLs8Hb##+V_^ zufr-TpO1FJZ$2Z7Hc@gSgQ*3p1d-`?tECg7O~X`Lz2)o4BY@xGC{6)Azk2#W`1+W=!=2wFntyQ@#Yg6i zur5g$k&!k;K=4D;+Do_8jkvG6cN2#9DiHOoKs{p|N$1OS8H(3_FGlo6wRI$2x!#eb z+$If=p4;)Cyg^&FP6YnOiwMJa_s?O zJ2!Jz-2HM$j|^i+7uW0Tbe`FVscfD<1X}pz2-Ko|!AfJ*>LnQ;`;;Qh zXYLdXo=_~sBd?3Hsbb=YDCR~ri%}^D2I|**2r9-5Q-&0Sy&2a+)&bW%uVMcs-O^7S zqR!J*RfHf+FgUy^l0ZR!ybvgCWkjqh&KxZZn-!HhYO5MzyzD&3Ca^3j_B0{PZXwwr9CiE7WZ-;j%a#(KZjH`b{N1ahm$;W4nM#!{23qmxh| zHMGuR9)z+&adpYzQq4ur3;4vVU$dQ)6~FN{8Ov|sPrMUTQ3Grmopp{*58IFq4f!jM z{$qRLT@tS>Qpxgb5es+L)jykg+nhCHHWEDhgg{wS`dPWMe7bT^otSpY1@4cE_@-W+ zl<6i2M2gIQW0T1%>b$p#9T;op>G{BzFCNX2Cy4q(vRRj3aU4H1MR9#}cj*Z(8KIKTm`Qy6lD=m%U>OlO=E9*MAbv`VH_gt(&6|a1%!p)8}?|p2jvmmpAqb> zAiO^z?}ra^{G=B^H{!X)}Dm-GMQ* zFnMrU^xT1&i_Ns&xfscnY_peaq{&7F$Jmu07$0=!-tMh3HpIqFPn9-`Z?t`J9_QU< zn~3F!W98Y|2lNbcdWTj%^4ZQK)}4)F0hs!ejaI6u)r^;N_sLh%_UMkEpnF*^foYar zFjvB6(G0r>Z;Yy-8J<tx;(&!rU_qEng1-TyV626k z1b#z`Gfm)4@E@1SN(T}YU9YGvXrWiF*Amf=TWJv*2a^@G5xp{MZf^FxGHb53v8inC zRXcK>@wOwkBTo!IT;=!4jXm6Qz2STDnQb@kw)**<#p#9?J1K6VG0 zQ8?7;(t-Q5PtJxzTLarJd?jd1AJ82Rg?y}vU^D3mCT?t{tUE?HhfLqur<(Gnt-aMl zt|w6~P-)SmRZM{;BvHG0w0%Hti|F1pyeS+=<(y+in19k;u^)m7=Y4Z8+Vm{3bz*ya zE<369II<=E>jSBQrdkN@8Xo=TiIwdl-{5ZHSz+vkgm~>ol~5$xD>C_uWIj1kKU8j~ zs{YP=NhTV}TlWe+%o*^Ghc{t8U->MXTh@y;*_!$Tv!zc3biZ5TbxDb(cP(&SOW~^N zS4+%Tr?TCB5HSODUhDhIY5eLTI6*E&6VzU0ySGr8u|*1^s(MHz{vAxc`v^o3$M4)c z{2U)@wX4Zb*$z}|M$G}yxM=%3fv(w~aUiU+LMWsFs|+xByv>RDI1o9CW=FCqKi&oO z0%aBFd;|vUG&)x?@K{U<${=DK#F3Z{0F9ZoeV_(-v?+J9vt42lRw&f|9*)v97j{5j}*sEp&DOUip4I+Sfs{b((=5K~$jh z6o#-mk`8em>hEu5rH9Ykd0e};R(Grrk?s*%KDeDhS0<5xf-)hM{ye}qwVi`I1k`%y zx2&oaC8#a}Bn(?cMIzTGke5kwaCB%gURTwVpWDxBgyrmNw{!H+orYZL(v_aAwlURh z6x9W5LTnDSwzP zq$$n7{Za3;P{9>kic5b4vs%hvEp_R(5T>F_Q} zFBfp#wM$;hf@1rhoI?7?u*vP0>cz+0>@G+9)WAQlY~h>GMYU4*HU4x@f!1w}vusx(U{kgY2a?fb15R)#&f1sdqNt zT{J)!Xju4C(Cx|oV)IBXdw}#27X)W-aoZ02Y+di;i-W&EXdkuw$T^U(xd)E?y$JPI z6u!rgF`u7+lov+7piP>}B)NCIu`%#h`Sl{GQ$Y7{*-d_%NapYq?FrZ(4JaAZNH~Ca zYSde4fa?2o{INsr&s8xwJv*cDoD@bJ9Rw(SKk%eFv8?!8&I^-}eB?=5O&&y7=~o2_sL$QLb-f`K1u%sAdJTLLOoRt9!U1vKj;5280^I^H0*{I3Z`P zZt(^_i5Q6Yz`uVtM`ZrqZYPNaN}uxNO4>EnAQy`#TEy+pCk@r7+(WVVaSM~mZYf0u zkS9BzvtG5A;!nD*FkMBTXAXn(r2s%czrWq1;Qe7a$}O!qG{~QL3yAThH{#5L)J_>* z@=}KMk7%gR{u;8-u3}eAvH);gL@bn|@J%bErH8YhqgS_!*s`-lQkKA#c{|B<)?ZwI+KB9(F?OSodCs4RDCs*6>Tj4CFHF$Muh963#p5Ga;&E|~E_ zh;%j(CkDI5-kisQ70>wcfYgNfIg%dCljMyHQm#$l&;EI@XwRs3DI694QkgW$^isLJ zhLF{TIuf7LyRO7Yh=LfN0h|7wOK!^F_)zMz(`x($;)#5v-zyxvE=T4^?8b!!acXz} zmCb74ltFwDa@+_zqw+p&4(Xd7Nx=#luS3g_v;%@W-GTwj{Lx0#G_}&MPWXd;PrNVf zod?MoO)}>Lz}y;J#2)_6dRROtrBRSJl@VqkyA27`s;!LBu53SIX!2FgED7Bcyjbuf z&A%8Wl}J^yT#!U`pATz$uCF`@NnJ{3*dg;mu24)P5FLdf){R>FczRPs3JdzITp@57 z#VQWQ4j0)`QH80{RdXn^I#DC^B6`?JDMb`BV@`_&1Hx_)9>v@~NRG(WTrYqGeIqio ztEL{Rau6e2eP0bs{LqEgL6E@nV}D4tE&JYi)4%TO_p8ss1Yaes&GNVU_~zkjyG1Tz zLEU}1lxAh!-xY6AgKJPk?c<*Ybtb2iY3O07751$n3?xm+LOw5&j}Or6f!BQ8mCLHU zM04WF-RbFYlGdYqP?*>ume;5{C@K&`?^5hMd>mg3Y1VD7^Ac+9@qQ$>4_YUADL^drb2lbw|^_F34S$iC%Q%|QL0Z`8=rW|Aqc9f+0e$`MW56hRV_ z`oSUf$+=-K~UpE`(gTaXK4IFW=8fRMwd&&SG;zREqb}7XT*C&DH`!YZ@ZZTXM z^2*I)g(!U|#?{gdQZ*D*SzmAzGsz9pC&R7ap{87z5=W)n_)=S0{kqRn0znm@G(mkNl1_hnb$#vnZ6& z^%mMs^z;*5*c;hE_L%$d&#C|5|9fV@ETg72O0=tK6%7mmF5NSG*ir&0_-B zAKa1p#P5;giV&~<`7#U2UQr5iA2P&ohxnPjL)f4b1<|fla|!@%u5FkiRZV?y{V<#= zR@&*xj_9@I@$H^5I@BFDq{!hVc3F4Y=HLrAmwzkw;{xoMy%BSzu#glJvC@ocW#&_}Q4!ji5!%z$o@Kk4`R2<*k8Y+iDKw_9 zkH#*N@tB<{rWruJ1nocsqdd4XI;Kfdmj-?x&^6Af&wh|C$0R5rDve0ME}KHE zEfd}j94pe_4?B&snC&Jap{L1gw^%%8_{JslHAZm|@~ULy)_W?U5~_f}U?ve?8quC- z&i~u7uhIw36aYDy12~fjf|!dt^rUU zU!YbcDq+*2cRSSyG#%5vx2KzOpZlbw)88>nrUH&#rF>_u*PFY0@q+5L=m~-_PgpM+ zL9>>A$A;?5$mBy4UqEX7xlS8wT5`QTru2A<7TOuli6BQ3yvDIvn>_fcTM%xP(h-PF z9s%r=h`AQY&mNJD()mhHvcQ$e!-vvqdDWG~(~Z*m<0@+~+b5hulSdl4<@f5XxKAq9 znl-)9RUOC0Q|I*9`GZGB(JjxHm5!)yZaT`me|pL@ZOXk*xE;27h?!k@v8>*LW~rqJ z{VB3eJr5>RAle~~SJDLCLr0(>AC$6R7b{Q{P=9YrVao2#dbxSTdsTYHdcs$~ID~2Uk^E_SLN+0atZ0n~XhzytjWd8iAx1^pArpyG* zX%Llra5f_w!{j#f;=}!b{Wv8L9-Q#^6tY-JZa5O=h}piXhQov1skBNhcg=CbG~Wb_ z`az+0ZJ}KYK_fdVrlzP}28uA6@TX-)cxnR(9RwCb_^A*n%0SCDI7lHM)h5fzrFl4!u&C4n=ym;hOA+k?zE%ZONw%~crJM;3Va!e`u&oy1NDcl+^W8`kl)|%yRG0oNnkxoPSo(iq! zz&|Du8WP091GDRT8EL5CRxvPw_DHtug}n_uJTSewXt`*(4p2#dGj8H(YELdCxY@{7 zSC==l>G9BTNy83SrwrpS9YGD+XpT2sQk;Qx?kb<(=(<0SwS{8L@W3k%*#F!HM|2uc z^x#>CM_fH|?mrp44a;~sI;|SDwp>xCdsS*sV&*o!<7&(rkD4vNzx(SXKuAGHmp7u z<2wf5Rc&Gfh&5^Rx(JMpd`lBHc|V3y1I>6s%fcx;W$;x|9*;!!mI5q%5xDHqf+5Fc z5EAR4&kz5=U4L9d%uS(g*8t2I0UA6|LS7gfdl(S=5VIbzt6S+;s4m!5k^%TM7>@lP zubg^dxqa4c(12YtT0db3B`63&dK*G|y_r2gur0p=gML%KRfifd^HyXj``V$x=n)b!EoT4RPZIny>~Jf*zpJ{xdlK}B zIn>V(9=J-M2Fm06%*yr3+x<`lA4GZcy)M^;P>K>t)d5R-NgFdoNnR5RGbzX+oC!E4 z#6c8GJ=1Q{VgM)OmQxLSAqrrqBWxg>4OzIT#n%L=}?5&5zp)4|NqY7^5v;&!Nk6~?eveo#aK@9ZD zGJeaD3*<#eZqXL*cNqoJp8O-- zgC5#|8h?l0C!{|4DE>ER3-r%1TSE^_h)Rv`LH4yCIn5lwcjr06IYrFbt`?cTO7`xt zKwq#W1HT2ne`W?u_|giTi22X3`O5{*y8+b}CWGmBXUtvi8OI0|dh=WQvwt~s^@CJr z5TR$x!JrC%#N}m|jtO9sz@$a6OZ~o7h>*nCY7`ihS11~!lt2cTTp3i2fOe!IGp_)?#vrHQgSNV`q5o9V z?cNIBDJSXanWVDA>Q&ERB|rO~hD8EYfj^?W5WW+8n^pMP#(0~;QxCNQ-!K8cVJ4m zmd%+#c0A1aLfr6EGuDGk(^qngq;9A{$wCnz6`7%|B~tvFT6}z-sUiV_wHjT!?7CM= z^H7iKJE&b8`z`nJqYVs3S~3b?QR^NT{y_K4LQkFG^hxq1xi+f}dZU!$mKxkNNxW{# zbmh1P)QKiCS;Zk!+q@O*OFmt}`gm14E7-9HbFhKvC;jGy`4w1_)$eK(yN=lr$I@cS zLRF6TA?Yb^Re$ZXOFJ=Y`IVZ(~u~&P=<4F)LbNLm7l`A z{nQ5BlA!wdbJ-;kIa*}UBTxkx?ZCI}7VYrKkxHkE^@kDDx z3%*3NQiHYKeP|JK2tu7GOYX4Lywa&4Zm^!(=GIFi%uUfQSY;DIvn{Y`*#_C!R>j|O zI!faflMS%SckEApg(3O$W|$u=dX62xLdL9P# zd3D3Sfa&D)Z57tdxN}&rRiS>52(mshY8f>6v>8v`0ZpQQOnsGFE{z^WWiyFU6m5a& z=bud;Z=`l5{KqGdm}LQ!E?B$96sxF)i5|?)*)YvJp&yN;EG_`M{$8X@S#2D7Tq%*s z-y{KNF~RA-H)UW*j>XX+FqN>6?482z<#Yy*7nJ!zhe58xz`R(Nl+gjr859^w+|(GM z!=^34qlOT(8A$OSMFkkr2#MhHm(W@GIt=z8@+`6YM+EBC*B*6&D)*LB=r#FyPCye9 z6Vi9zsJ^c1fN%WRyHKC^bms(bI27a84<2k|au%jbCRPN?xickj%sg{b+S2%Tw-ntE z)6M}um88_rhmsP&>FagKcI`%CD*iOyU3n7{I5hA?$>~DW7Z{bA5~+=G5^R9kFg8?G zM?8#W!}@DRF0zbbkHG@D@i3?4?O6i8-_)LIbrSnH_Y;>om*Mcbttk)|dOsk(7w8RQG5{=~{Ql(JS<8 zGAE0!4;?6*X3eXjM^Gc@9$&V!Lioi+&gc4HRP*Q_U)P)kZ?noDe7Bb?7 zFy#w0CDw;jyVpk9?k;ERX7Ahp(H}O~e=P6G zn;$x@%niqywWd)K5Z$+RvGt_yO$W?)eSF=q_+j%d&5_o{Q3!K$t#XVtRVTyCd*zppTc2R<+Cv!FAy4wyChjK!7hXE zYpy0eXFSrf)iQ_$I8S0~OnimPmV$S{pwYIuw4a(pH1s{&kv8Bq5W{P8gCAJf22Op; zmNdiVxUho|>rX6po;>WPZf*)$1ZkuYUYMg{yf=qb9Gb5+1~T^{#*ADTr*Zb@2|wh| z5exL-j%dVMVI;M`7!q@e+RYMxOsuv|r8Mq{5kNG)B0Q4X)s*w^&K?zo#{?t)eSPJR zt$~i+mJ=h5br59mvFAXWVCSJ0{u^pj9`E_ys>^cxEdC~ij{vW(PXblKQUaZm=j zlnyw4PirD{2|!Ur*0R=)BJps9s#&3Kexk=!y?_xYgQqJS3bGQS4Wgi#v%*yCNHvm@ zVj7>)B9q;BD%KFasR(4h~^s|gMIIHvRk8C&&WaTJRhdqeQ0^?I(tx5K^J@-VfV zvsFm;L@@8l`y*h+#;WaSpq%Yf22cmmf!;1!$Hhb~@*ZYd=4Zq!O;gzUA?8qO==S|O z*mLf+{HZ&AiOXDTU_T<(R{yJ~PECYmSm7spgLqzUKg7@bZy(%|ig3mlCqf}A)AHGZ z(QrD@?Z@`$t7#pPre^lpS6hDEGsn-mj}~Ds4NJ7PE8#o#I|7?HxmE(l=2dc4w1~GH zQ**7AZ1+5>Dcd9jhHCaUmQ{rllp$cfR5E+as4|3!+#x2Q&XC0Oy3QoSBsh^v{%wnqk)v1` zc>@sXf+VH>4#Jn;d?4XJIlRd2+}S`=-c$^RL4_TZBR^hj zluB+<{ZezazSq!~y2e8Ms$U1#00~F0B~}hQz{mfEg%)NG*pP&RyO^_=Q^dxXEK+w)s^wiJ%&TAcbD0xZ{kW9tHJfEuHxj;;nv4Af>MdC|lda3`!!kjh zE_2@Kg)7F}EFYw5a;o>5s$_eh_}+8MX#=Y8i@F@{NpAR>hgi^w&r7M0E$Xl((PJ@xPCuIyR?|!po~I4t*##!HhF^N9Y@eUK ze&}fOW1wCfy2%}-E%st-9o0&yHLJeOuO?eBS9VsYL~>tO$mCKqz`r@WElh?lN;LYb z9|0 zHbE7!cW3CQAYT5M(@&qdfPo_C40rhQY#Ukn7@C!n>6V+H0Y2Iu{P4*-;qF^RcyqWO z9Ep{{eItRxW)a64$A$0m#IlG6Oe?^)g@F;)l8%(|#SrQ2Bf9mL$4(X@DNfXeQ66!L zd4L4c`R+Vq?S8lW^c&xa<2?Lca0*d__7D+o*Qa6W7J%fNcJ9W;@umy-Q|V+k^-dA?bGj_U zkCWcYPNk%HOuEEs<&(*#E3|M|^2uwfzBPt31_Uee* z|FNhjJJ~s!lKy>@H?lM}b`rL;u{U%y{PXo+tNg#_hMRRxwwTg@&j-A~3NiF~^h;Bs zBvwF63N}rAIAKrjH*8$m%6{VZyqQJCl0q;bg<~$2LGzDsM4P9G5iem{uFqrvj;FYG zUZ!O@e5-wd?14)Vf(>2t(l)C-{HbV1Yaj>Ec-_!wp+=c5&0nD^u0Z`1o+$icQGtG40v2bI9~R z`};IQDv#Lv(8}k6{)h+ZV6(M$vLgV_ay%0gnz0D(G>igSIMp9)0j|DE=9GG)Ce4CY zHP|;*9lw80`I+{5%3&wPhowx)5zciTcuC28zfwD1TsNfQC_4hvRoqdT`yGq^3SJ5Y z8;{u@OB{>aia6^Dgr|v*1H~j_&P_2DpcJNC{hKz|eD1g$r&xEbkbKw-nmV~6Xw!pn z`a-suu+{bU_wP7IfMkbo;QcWvb^?0sp7wqTzHVx7ORUs577BXj@qHZ;qVvAKdB*{G z^H?TnbQIMpy3hEY;5QI_61ZXZ)Ah2VF@4`2+s{&~p1vW&G>frTUGl$};+vo!J0vA|{F?lmUuB zq)CD#Rs<9@7}FsnLN=Jxwg%SsKpGLy{<+$#moHFVg^n9h4H#1qfu^Rg6VW-=pshtk7c2rmt_PT_kG0kTiY4~HhXd`#!(w!(UMEn zBTd9ii!=6?dwE}Q6#oDJ0djN z<-7u&s1z&8K@f0NCKd}glTq=gM?LSMf|y9-@-|!eGYe%e*J%H#v~e`+Zd@{n4%;Op z>Zprx5nHJt@zVU`fy)t?DA(l0;^3KLA>Nz(WTu@{*eV<7!E5ok-8X-q9OxH%5#`xbq7+N8f~?ua(pJIahD_+Rez&< z{t4b0J`xHF$CDyQ#=_CqmkZSU&WKQSR_2lIqSp+{1do2R$PhVe(>PkE*2DATqVMPH ztttk%9V)ydpvs(;hCCfqfCWxLMN45(R%qfVJ$Ub*{o97?wi?V7gTx7CA=$48y%*s@ zbInMCRU08b@Sq^V_={J-XL6CT*mnnF1Iyadar#Sz%GyzI!swM~O{qC?{=|K*s-!fw znRM=6Ll!%=`JgnC+r?8R_NbjpMd=gk-6>4Aq~#LaDwcTDuF8?2taupkOa`S3*zq?v zR-D9+9er-hmD(*4@j8h~?pr)5a(qYZTn_Vf9^+!9%f`fTOj|i@)(FXX1#L44&<8<3 zxXCV9NW%yg4R*^6epp~(!j}jY5t(LUvm~QECxt-sN_O&DQAoSMZht#M%_$z3plJPO zs3A6jbi`P`M@6N(jwLUvM8swzqtTT+bVvm+e*js9uKk!-qR=E!k9Hvitewj`aYrlu zs~hwq;1xMX{mvNN+m(FuvYE3;TeFZSIg53H78t(t4n!ZegU|D$X!?+H!|BHtej;IB zV+7rCshi|*B+UBtsn*IZ%V$=D5)`qT*yZ1j#Y7A zrnrP!G>5qDWqZ9LJ&abk>}kh*zHt8W=HIA^xclpDL#TH3ViynREjZ?GeXxo)eDho}s? zT9^|KalfZvwg=?W zwA-Ltp4H`~aGSH>%t4LC+s`BtZwF=pvT74*h!+r&n!Q3gED$~XS!+`4GaCDXl}`@^ zIc924wSwx}k6?PxVP|)Vz;6mRf0GR?&Tz!M|B98%FKK4lG5lz z+P4)Z7WnK=@Ej!Qv^1T&>9$pn=2!E4Pl{kmKK_LXD_x8@M+P%*fSt4`?pte4FS>V8 z8y@bD7vnXpqQV)QF1^ecSufzND`z4F0iesZvkezWHcD%PeM zKmLR<)4VGfkC_7EP4>W1@1L{bX#s%NFYFw78&G~i!x?sF!pzf}Y}t~)L-u=ZbAo1s zR4p#yZL)GYF;tg>&IB#=XM?$7^83pw7>~;5g%-($=dB@>1eJOlZ1Wd%+4VU-$#rA2 zwn)j1nW87gXT9~0v?e`AuTOT#jU%!v&z-m?-JP^1P%Ia&Ux6P%p#&IHg1=X&L_}I} z9P1IAf@^of8)?58!jn2apZ%J6w8&l9ElQbU*nHPYCqI^QKXodANwGTY51SX}7YEgt zXj5Y*L_RjcZ>-OGzWSLv+B90(O_0v;T`kSHe|B{1DQptY*0JIR0)x8s772tJ4c+jL z0pi_v_rbxuKqN(6%E&#A0Kvg2&Eb1Ly7*y)GZxXLu!;NQ@1cZPu~gHLPSM|5bQ&H^ zkSN(tH+eGY7%3jH8P+u~lUkGqCrl&GS?0q=40xq<$*YL!o%3n{+axCLlZfbRh;tFd z&2T1;0D$co$6ITI*pz=uEs{w(AtK%yj%`~&5fss7QfJs*0%njh0(-0Z&y&W>t3=vK zRI~%q6FJ5G(uYH<`$H?oqX)&@rX+b&%m%(UxBi_&Z4oK4Q=Kd(^>Ry&JZn7xIb40x z+FWz2vBu3iogAFyoCnL*_5lIFSmzdOnHq5-_q_ajWFh}7eyQdg!(sla$7wUcJK_-; z#aw5bybcwchdD9p&+=(gt*Sngb zwX>18G*bQpa6I-@+t{1`CX4N;4223Rfl}HRN)UGKyTlin3Zm837Kw zVl4^83XH;{@<2M^lw54H$?DmWeRt|q`^DzGGT_jiu`K^If+8gnKkoV@0sq0*x9dpD!;+9!;W~3y zpfm=-4U3o~cMK*g#ukxG#;P?QUyhC*XXR3o#2l>w-EBoZ?^~`ksqnlAJLYxuaJV@y zlR0*~SICd(CvwnO=mt13w>mXmczNhcOoXx#$@)-avCUyl+p*3Qk_Ykec;i z0CvZ6xUE-@$z8F_k3F;3-PO6t2o>K-62EU&2I;F*nJ)TVLjh?}cX567vL{<2@pvos zn6uDX4>tb2IG2(kG3Ras`b7;BplZ?*LZrFqe_G5+HOCEdxxhmten1 za4_0*Q?*uVEUbAfwN&y=5;CPRvPxu&H7X8TWQ;X8@HSY5;N90Kv+qqcN8!5!v!^ml ze=#@ZFIc9Ois_}AqB>7tqHMOLr5)s0sg+HX$xmxjcH-XHgKBd#d%L~g?ww@Z()X0_ zsSTIcBZ-c--rCrzA6vPTjI*EJs^)^5h5Cq#&l-LAzV|ggPt{ZPt%|wX`?$>K zWFB$STAm!+3P;&cmnY+_Q9a?_pu6ltxHE#|N9MSHUFPx)%!NL+a50miMRxaP=5QC; z1u$ny%=O82WRRNZzx5_VSDl<&kRl}L$$qmv2%svC&b^fT;X`%TKJ3eao%Q&^D*4E|FZoaHw!28 zg}$Tm%h<@^7n9zYj;+6#8MkKF&vXalI@^V6tnApmkAXI_xPIIj$w^3;-rB5|dF%(_ zI#t4aHpExwEnoIbPK5AY8MS&PY^UEE`7Zkb&OyiQ`g7e4af8+bB^(9|D+#)hVv7C98LA8mt2qv<;py&%u{(|rte&sJK_Ol)_v8Fx0;k=zu@La$P z@7i)hU&GGNIs2!Sn?o0tkpe&&vk3$h+@p+sa7S(=$1|^NY9srukZ4e zHtZIhzw7V&OKUIDoDX>f+n`$N7MRetv~WEnluAXF$m(V~G6F41BxYF9eP)f=G7ODPt@GU8(dc`)eTN;^UKB~9j%wmC8OWQiu!Fd!YmprYJVp?noghF z^&W&@pz>e^X1BmdqIDGI^CfBXyb0TUrHRerpWJen`>oD|@=POVA=waR=#*D_PZqX3 z@o6J$we8TOrbN1aOU>?uU4EQLuX$ZaA}J0zj7{Q}s2zUZdA-Cy43 z!mkKEmI;1dhl53kzrYA%o)yEtqGNndbRSAWhyuNa*tD7mt5 zqutbg0F5UKz)ku?k__Lh1-b0NWWV{10e*0A(P`92F}UxRO6fak zzift=G0bU48tL)biz#~1!aBgf3y(X&_CdLb&yCWgE^Si5omM!#+hCM?2|nnK?mPnd zzSX(_G7(4a?>eOcocbRM=Ea$w&6?D4Be`}NouDCwd(n3CcW=}p*cxRUUH^i7`ECP4 zTr}`M;imT+sAOL=5x0{X&t}_J}uc)fOohr ziK7(Qp+56fv~%JcaFR7kQ9J}L9Z8#9j%a5Bl+dmpidPS~wLD@TQg^E3_n20=Egt8f zp-5U5of7w_3I0TbhbW!%6jv4{JlsONx_X%jW?dAXy#6B#odSOOTG6W6PAN4Q&UN7A zj62-obp##2!8<0q)$%c>TaO}%xOs1&-~&3Nbs=n+XH{g_AtSjtPrs2CAV((sB3;%< zOlcJ7!%2V*%ogbm^p$BsALKI*m^yJ6O5p})zW=n+Rqu^rVW3xTk$d>HEYPQS|Ad42NtF4`)=Pe|^Qtuc~B`2<> zAGj&F$)F4hu=gTT;gY9!x+{*vgx_W+65hsE98Q0>M=lMaDz|shtpA4iVRN^<4bR5z$ z)uEi}25b2O^MEUqUvm6?exDwMqO7K#SGO~PhvGgM7B`l zphbcOD&Tc4GU1h$0xJ#+xM|5%6I}y#&H1mOjg|I~KrL6c0oTIDbB*&bKq~ue6b_^7 z%H`$*BFlm6`M|>s1s0f*W4dGQA?GFQBF&6rRfi~WA=!gG#BGlS0@yR85uR={2Nj-;*r%!j=(HGf(_6v9`>&!4H_&zc zSSBlN(kVL4_fupY{ANNL9RY1Y)0Hi@!85tj2L8V}&+ISmBdunPXs0VK{X-6v?s^oj)51D9928 zXn~8TSv;47zk0;AZ{8W$N@!`X0N8VPKsX3?WGxPU)eLQQETF*&`NANncetwB^5uOo zaKRm#3ry?6;Zz)v{MRXnjkRILCiv+Th7?o3YMEkjFHSb{s(N*PdP+{?c-?7fSpBO5 z_z7wj+G<;9J<#+)pnojpbaVxnwi2n*)FTXMlZJ6&^=>z8z_Sn5|9<+|ook zKv%xTq_Wt7)gSgUP;63UXnpAfd=K}yaj)q}ROfa=J`NU9WNDQ9<2`&FRNCV3NNg< z4;pnqMoLoZ_=z}uB^IFL{I)GMTTci^d^u;y3RYNoTnsW`5Ju95pHcPU4!28);RS@`QQ8+<-Ta$WqaCh<^_jDoE_E&&z?OCv6r59X_iEHf|LsfwmVN1_$%1X6` zxrrkO|DsgYWeBTfYZ5XlmumGt?|$Q+@7=J@H|W*!O-ZgnEdbBp+Dr_AAczdpbYX?!o#Yn_!8Tl@^%YVg$2zyk|ebcrZgclh)xNFehnz%O){9`cD4eeNA~!o9(UZDYe;u*mEqj1zup;_(fl;o6Syh28uQ3 zR*p}HDR%FunXtb=d`xg7Z6)Sp^>m$Dxus29!29lNwBjw8UsG-}VC3z9UJh0|u=PAm1H3ak*yR8|NQ z>X71U0Sc)D9sLC@KA@U1}3&qSGMn_Cq$!UE+xO{Js9LhH=d$>0YN!d~%-sdwbeYr0>O`URu69G5heYyS(r@C%i>^EU)qmLf@n zTj#DmQhw^G!marPzfu{cM30D8-zto6Dzx_*!)N8szuM`OVkccyU_e0Cu>VdDIRB62 zz}dt8pBz@$&c?>T)>!4ApZ~cc^5Lek1lTe&WqO%DL=MG<3T z(8aBv#P0)SGh)%q9IO-#IhBWryLYq5HK8%|)y~0H@y@$I)p1CXl=e!UI%yETFxPlQ z$ir$JyNsYez@*fq$#{L?xxvuXInhkZdAM= z-_6gA`;TZ$%`sfKQy>|oIWgz~_G{y4e_gHT(`V~-^O%iBPz@)Aqi6|+bq3QgtT>O~ zpoDjs!Cm+D#OAN|;G3#r*yA;9K3Gzo>k$dBnH9qF;AKbf#7O>@6hoH(q%42w1~)pNX{d{T4{A5$3|nf7T;C zb64q28#R?WfjPj?{n@fo-gzKl^n?v25z`Q_6)?|daCxl9oDbQr`ZG&E+XNmA#*cg; z`O6?evG#y6fJ^m=3%tB1+kq-1;SU2%ogMAFH2wU?0{A&nQU?mS3`>JBM0O{y&Q$b9 zapJPOnu`LVjmbz=0 KBP{>0@fk1itV-qn=DZ|;p-%968q>U2tj%j#U~ns&y$%Xn zQz;onE=4pgLapktn6UCRLgxm_%}8!>*7>Vm z1+FL_$_VQ(mMI6T`a9b#kKXU9XD3za35^z-5PU$7c`0?+x;%YC5mP7E(Bx%m zuoa|(`{KfpPj56`^1Pa8 zc*9saiDp~f>snMAOpneO^oH4ulWogKDqovJ?WX*;(Q&X|W1=?gOhy^vR6B_(HCbux zfT1snZC*+VM@zJ#bn6q5|7NLWCwqPk_Nv=!GWl-x%9|{Kj!!={vwUv$(%(wYXD697 ziY~uY@QnSI`h;g&wy)ib%!F9u(8D7+w1Zt`5{(a$({lH~?OC|pIAUeiu36>$)iZ*h zMlU@~ES@dUD7HponTCA7P*y&Sl^$1kC=b5fpUe3-mFsju>&UUXc7FF>pCXDQi$+D- z;-idM8Cg^5o6#eQ*?B1W+NDWpCZ8BVk%r&TWC`CQ1z*&^^0>OaCA5?EviiyK$ohyx zh5957A zm%*682DS)W`;O&W5PT}lAdP%U@-3BLuTz0uS;NChyfNr5TC8Pfu-x2fmrPDP^TKxD zx{=czA+Qh)%b^gwXMvA!kg$dy4H+_yqKhyD( zr9V`rSz9UDL^a;T%uf0d#&Z9?q#=Ic4yY!d=mwA`9`VFphv8c>_g`-dTAEmt56~~N zv3nAmLSv6W8hKiyHj8MQH>AUk+6s{G48sp_-m&_=h-b%hUT>e?9Uolov5Mlv&)UAI z3SR0x^zO3(=F|{#2hJbn_vU^*92_$a%^Bn`O-H^FDxN=b&E1C^BCy$)J%4WQC?|o* zG@-qBtZ-ho5MD_O{LQoS&py1j&N~1cQn75dXjZCBHx^|JyEeMbmMuO1E|+UHUth9KHT!PSxKuE8!VbJd;|kXT zTvhd3xLv@T`d^x_AY2ceG6iSggVPP;zyxag^1^Ei)=Y0T(7;m+Zr8=Oj3G@BE{?NP zOdcllpEjS5Weiw5x^m1kTAA%FNM#+Gk7$@B<}?B-s#&Q@Kym{WiH_OOKnE<)%x<}Y z_^*aX3Pu1XOd~$^LjLn3s;|511k@bTQ%6{vZ=ulX+-P8S$iU~BUS=v3w-2?PXygo& z_Doi5rZvj+>DAg|z%(iWSFRPghP8a4EGT{6 zg$q=f*yt-f6v0xr1O=%r70r9jT8;JViD`HW??;Q{L=hx&%*Xmr4_08aR2`N5>cOu` zf09jcFaam*5tl$$xr2~LJz~o-;b68r5Y(YU3FOY_;!(Up8mlOJlq{5&;dQ0n+q0Yo z@*nzf!t25u`j6Ly3H0yJ4B39cYxs~;K`kOCwXgVnlrjdWFe;2xu5Yp1$f*Om=Yu1} zO&n-{EX;C$>%n;C63qQUBWpfboB=(Og|4E^7YeWI@Nw=)fq#Eif@{aJCCye7tCaVO zdb@$|{ptrG`CGF0f*E^ve~^%O-$?SUkaPO~X+0$Klbp*^%|e}!QpY#k2W+Ry@QGS} zVwdf6e;^L%yRVV}K6bvJw6jv8zAvuQ6cqh^Aq}F{Ir*0-nL`HHlZ*cKk?P)k-iWGrl5+(k^Bteoxa|K|~al`^&o zs_*uuD@rqMw7`U_rM3jR6p*&Lq(Gc>CURazpsY5%bVD%hn5_&O#m*PZ^eOw-B47j| zV}0Uu^mR>tFX|uu(4Y7`I8qKe6yfh~IX!pIcuYG@uYJC+#C8B}50-!+3@l{NN?I|Bhmu8SHY<}nM6sCBZm>ndlRjy1 zf~OeY#s?Agm;cJKXt7@N$ocK-;c_;=E@SD!H^uP1TO_gs8nThXJ+vDwvO;lImB_66 zs@lj%p%j6LIc;Sw4k1iHcu*LBFqklQ(0!^ESL0@JOPnX9c*kY3*Khv<1_$j{NkxYg zGSudAeYKG1Xr~~W)JI>m{|yW$c#TkwNp$U%ai>0jB?Ng}st9K`D>JTCe(c!PYMXL{ zbpe)Nl*kHgCAPNTY#+Kigjs8ym0ztW=<>|Y!XkJe?*Lb7pFw5MUJdOqk!j0BK3Et- zX-xa4q)DV8dL6yUKcqqVP~BD}VJ@*Ly2VItfCs${cS9`SQjJ6BF<7~G&(^yWbh|hM;;^H}tr07wg(Exq_9y1`DjB z`N{q}`AOV#Ia>S%zwQubD&WRq^mm5okjuFMAy4lIG+uX>QR#k$C>;K-@Oiu<9X7XS zY2!d1yF{Y(uGIaKq6oDb+pA2q)hncCs8txSDU4V#vK`6hggy~glEQj<%HQL_p<;e7 zjaouHX_^JKZMIFz^z9ukM}CI}F`1!KaS0}RADyK$*X|mi>_{F}5AY+vK6$@4u;QyDXF*2fa&Z!Ee}<^ZfmXR&g^6yL!38_K_7z6}2G zV{PdgPX%BD=0hy&_F=7hXo{b)-A)NF!b$@(cBj8|XB=d2d?PPBJ8me+;28#P=YHgb zu8C;dp~}U7KS7fYNQ|yuNO`<8-7CVcbEZ>@kryu1{`g<)Tn9k}|5XRFd;)?ReH~_L z<+Pn+I*k$3A2>{p^lEpwdece z1vsalTIq4t9mq#ThCe_|VwyrSKd~n_rv?YvPyik}RtDMR-7xWE95G<<6 z{hMHsKuIG3wI>cW?3v9;alJIG8)~;qXYdUErBu7@;1gB9>9~ z{DbBLtAU4Hv*wF^;^iA*0%{zWd=s=ji)072J_={%r{u%zdocoK#6hd(-MQ0Gc#Z2*`H#?w z)V!UTxDdfwje{o4@gyI!*N^FqohiKE$3A@v5YDg{mNketvgzz7-4V1PbBSUe; z>N50%DHpDeWNJdWbzN(-A$lOQX)}wJ@g(On3kPThJ!YjCgN<=w-8dkI!#Xuy_C9xwg9b;A1ip#`w%A3l!uKrEI=)nM3n~IR2A0&om2kMmw8zut% zq1-y5uL-SCgXQ7SE+Z>D_e>Wvc2ZspEQa^*)={f4PL3>^IM}7nH&|%yD5(s4mhGhh z54FCnGh{DJfE=#wD)}z7=3lY*bHRZ@E=8uGC6uK+FjffH+eliL#x@41YF%Y|WPav&u)J#=*IjoCG4OeNLW~HG@7(7jWHH zcroJKT5J`It#80NUgJeq966!-QgwW{(N2%hWfV@##lsZ55^V(H#TGJ(CRXVn2br}c zmZh^do_!E|T2(I1$6Hf~#to)LB=c!a`PcaPB&xV^-hj@w2qVf{>N$B1hI_aeJ_ps@ zPUYLtq^F_~s@ z;TO+k*5nD3<99@Nou3!CfaUuIS3z1~iF&m27>$J6w~Z~unXTXmYDrsJr{-ab9Mokv zdi3iMz-VaPA~8fy?@}cQb$i5e`YinS@E=i3tnRU2R+Ub;(&0``#}A~$Q%l!1(SD|9 zfdKlL*WB&Aq>(abZ#{8jW*(-nd!P)VTP*ew>yX6!DV<%YRjL z+wwM)>?}JVS)?yja_Ob6yP_)5XUyN~;_eK*q|X#C5)cZ7<$VO!ezgqfSM|=E zzOyv_%w(mWY;|H#7C7B3lg6qoZ&$=mS z!c$KuP90(2#6r5nwr0AK0^$R2y-;6AJl}1;G`5cC2WH z7+;beAi5r~tlzPm#d?9$w6Ze4YCG;Vv@*X2k7wzy&@Sy2QPIqRas|BL=jHB(z*@g8Ej^I}n zZcDl|IMSj=sMCS*@MllsdFx9V`@ojVvEg`ITpsg*BlEHcH>)1Ab8OVn;h#XR=l6xn z&fT@r4dWaB+};sZpNY3J@3utIz1;Ntnecm>Ky*bb(6%VaMOn&9X`h`y#mEE^aIMr8W*%G*YRUPbMZeZgo1eZG{+D?)dg+hpB$Ok7G{ldbZPz{82o84y28v(BocKHAZo z1~tuou;pow&uT~fXo`Q*5a$x#Ig#icLb=CqTa|~d>XUBki_`3M>4OUJf7mYK(#Jkyut z?@3w}R0D&&dM4Lol0Sj$7~H96wi=MB29Fezac=ytU>f5!1`tGH()|VqOY3`|l^a?oi^0L$^PbOaI zPs~~8ggfbs3pQ4eB4syzwHOk5_{^+EJU#?euSAt?kK*MpCNGc){PDhcf}*>^O*wjg zu-@djzp<-M`nvwtz{Gyw6OtGN5D*RWzuOJ)e>O1j-)b$d{67`Qlsbw!>Q9$Uf@Hrx zA|aK20TCH6U?^4%5;d}~gskWa5}98s%s7g80M-Fx>f4thh9_6v2M=w zV0X`@M(OEase-PXRTe9JCXk%Aa`eYdq~N)lhQ9&eJ=L{XuyfV}9ctBSuIUO|^A9j> zeM9M&LRv-~9zJ$BLX=DmQ|G8bsPZ%km71l-!HAIge>6PuMSJZ9`UG(dAxn5ZM7-Iv zWlUS>>M=`Bc%eZcLkYrW<$LvZKTQP!Chdd>af~3tS?s?YzzAy)!Vt*|+S1noI@#(5 zYZIXRA@B8xq1WqT4e)uHkF6>v#Ev4nts{&%MYpsTsmW49m_VRP-7!l6hEuC60Oo{T4rlFUPsnMr17 zy5Bs36Qg6JOpQ0eDh#naqNbabXXv8KO}p&Bb~@`XDs%U|n@C9M!4oOP49b=-%=;3$xR@6bJ&;(}VI3&<4v z>=s3F7~6dm0KVOI2(18Ei@SG%UcveYZC|Aid*$i{uN38@CDSVzC~<2vH`93SiQ85+ zRwcB|W^tLzblYiF^}-~Jq(eyr)j*3sjTW6>raWvwwSV(Q+ZE8?luFi;ZNkuauwDuQZ8ieio_oCdn#Lu8xLf22yb9{vO==bsd{GKYKK|*-Y z;05HtS#f@3A&mjH)w?^r2GxkGy?JVowgmaSeYb9h17V4e(MWdF6}TUa{&HDD7$p%i zWp%rLjrP2*>=bGS**Moe@T_Yus77PL-=!QIy?^@UcWfgI!}hO8i}(Uq3GPvcJm~v9 z`HHHeUdJG=AZHS#$P1a{KJkopYy%)d?(2Y5&cX2r4*qT*-mQ&r65|5Q*;?6}sejJ;6y^U8wZ5pMx-2t9(8=6`c)*{LW|kBb>n#J7*{yS*T$2QM-I=efDtw(olZ&uJq#t^HfO{tCNVd6md%uHn(MJC zXF}0lOFTtkS(Se8_g6MT%xjGYW&6v&3ZfzcSZpvbAfUQ`dj*8!KR~R4qluG=^Z%o( ztg5Y!t%~|BM>a-c;LoB%1xl3shlD^mPS0G4uK2fd|4`^3i!L|==wAb%%qTjYFI(g* z^XxwRLt#=jm9As=Yx;Xyd~X;!mFIlq1H5#!d~wWPxm`V9R~vh&{C=Adw`?*1ywCtN z-KDCd!0L04h1CWZ)s;(JFIje3mkF9`td#Rh>$7Gq^+lVl^in&3UTB7kjkdDvl$I)a z)jXN-QwoDd9a~j@Df+g@ABd zg--2iFJ(VQQh+b%lUay0=5=%Hl|uPoVS5T z=T{f!)Q}S72d4-txSquUu>92&pRkj$(ze~J&{;p)yjCe&Xk!Mbn;(G-r}c6(kpcQk z^U*eelb37#l;&l|8~5BF*N$9xZ%7VaVma=s4|)M$3z$U_F3=_f>#{Ap&uQ6=*5j;> zv&9KUX;dqBcqY-R(oRyMQcV|8g6G!P1CoG7B^U8fqoIQ4fokE_Ffcy7Jt`VP@`J7* zjD19fKA)W2qUu>0ciBE_?-bR8v9;p+wyv{RdQjn4%n7E(#HX!#TpwjYJXFpyhv~Qe zWq9ENp@;=E6^n16QA1EO{Cn8~(=(02l_QSc*77yihWXJfZz{?$g=Ph+<0r`=ay2g& zN}tUHgZm`$a~@&#ES#&-ySUTpmsqwtaqv84*BKywq`eC|IW1R$&BAa45pM?^?tDCJ%;q2%Vsj*HZyTERFdj+ryqZ6t@TKk`L!&$CHW9xsR!$KGD% zGkk(4Ey2fqnM4ihpP`CjY>Nj>qL=6`pRsyssRJKL5wY52o)j89bML5K5o9;YkJ-bP zM9ou4@=2dsplX?ALcw(t9!Y;w;2)lqU_Akw5>(kya{Bw+kG@Wj*BIkzKq}+lbOZ;P zx_xaoca$g6Xjwt6ft586C&p8nPYOd!^HaJaJtIvi0cH|xeqf^BX0D14qXSwJt3U6x zJD%>4lELAMRsrx*C5ZwZvjXcBU{Ucn;xqL^kFByV2}81iQ?ahFiPJ$y^DDg{$bx{V zC9nT-dc+uyl|K86SKS2u`RGh`58cpLGk&`Or1+p}lWtBdZu`!|DOjjHDpAI0JSU4M z(4d6TbWk;Po;GxT+|ZQjg&es=@`|*whnplgQyOxL(1?FyOaLb5x3Vy!-M}_xAR}VE zKEbY!a*TYXq^=4G1se-G>-c}q1r>`&iB5?4$@92oLa;<;w~B6X$z^(F9{XfHCIfHDp5#x6mBD9DZc4?XiC3#;(HVV`Gw@i6z@wrJ;u|7DgVEVbgTg8qNe zljT34r=p9Uvx(FHi%rf_gDM4+G!N58u%|SeA&{@b!WO(tYrgKO*^iE%AUkS%e!JDP z8|AxzAlLIMsO$y61@M1RJAYzKyK~-jXy*~e2;+wOykx!n%O~Id`*u`|{|pp05Wj1L zsmHF=-lSHqELLxA1+MQPSzxmvFM6lt`I3<7(l{r-zrb-p@! zF;JDBIcpUulX|&X^=;4)a|{=Ob&8+^@eMj?zuU5;Ns;M!>P^ZgIumIntC|}Xik95JThPjSLxOaZSxU%ineTH(Oa8joYVNZjzg9}?rLmp$)whz=h0J>4eETa$q zPpwjW+ju)6F~tE(&>TVRc7P^6%;9faEwEK>4HPX{U zwKjbdeH!w!b(%H9=+v4tx^f^e5XJn&&W@5Jf`aneI)hEve!#xrq5y8uC8Da++*_Px zyW+_JTBAyJ{BzWu2AkjZ!b94Qsx`!|{1w8p+;$a*!uOJUFu<02bRTzLj~S=EiA*-- z_;l!swCfyd`FPI7D#I>+Mq1Tgy$|k?=oJWG@-^UBfqdCyxN3YSoIrbV-cxKZNcqN@;RMwfoO&` zjCx9J7RjN0_l#X!aUSTqfD8_J8ueLowk_$}AAFW}bfjvfTC`|U8Fy!^n*zL>>L1T`sbr)%%t3L4;2^W52|KQgvRa#ejl`D=}xIDujmW$BlL$(Z|yUTm%u7U5b#q%9YhE&0@zY; zU05(LO~_(Wop=Z@o%A`Hfjsm_w7G;@Ewnfn)t3mJ->)t$!r5MbHApswGBhDLSPQW7 z0L5woc7}4afII{G~_an#hgOBzgO<*m`&WY9fIdJ>-&D5?*nMFOW)o7LlQi9OIhaZ=Z-? zNkQOC6G;Whb67Iov2S+IeZu{m1VCu)y}yjTSG92TKAX>Oi_yadG=#RfKLMgnYLW?T zC%K;Ce`o48nV&(|)9LfWUp9ps{mzYejW2zkUT!3F`stM(=V*T!s>oyspn#^4yoHY9 zm-Z|Y5+-baLH|ai4%C9gsFUKu-zN6s2Js`J38;tP!4Jk7{-AJ2<$s}o=PzA7QS3}~ z5A@P+{0GHIDMm?NS@yLG1LULZ5f8=)d*_5H1J_rjql0`C6SSJH9yBZ8nI?A}G|Wj} zk@lq#N38c#h!g+7_@zf))kI)40T!AIk zgHR-C?DVx&doq4<1*=-7^iiD&V>?q&coH_`eEmGnrj7%(byUb|MUw^Q6583$ZQD&g z)3sw~IxBie_bLD|62`4b6z3UHJqUOD-|9&kVO7{z*{EiDcv7;^L=cD>JJbe0|6>5P zn@H~lAjf#Na1F2!%fx>U#*&&y0Lpf;8YmWU54^&+sR>JiN533G{)=b3su1?b*W9;} zDRNS)V#C>7>FULZ+y?_Q0lUNb^+>EYRxSX`Vkf0(BgG?u4G9-GX`+P=S9O)7j?%zn zvi@^3$s(7rLW+iYQ8To+7$jXvrm1I+;o!=)l!g4v%vYfM8dp(f}&%+!-P`?>r!JA}ihwV^?=S zzqP>yzb|`ikjd$qMXHcK30PPWi}pzEgvRhB>`5eTeaBxLbionQMSxjXI* z%a4&};;&^Kn7%DWt2sARfwSUHdu&^>_+ba~AXjr#KP8E`&Lq;7+(N@OV<1G*UviLT z3!AC8O;=(pB@Uw5n;y3};qUQN(n5M6Tk&shBr+($xQlVR$;pbRTv?nDj=<$QIK zkL*M#jH0?yeP8N(c^9unT*q~bjKNIY@-;00nqq5;$Va9aM;$*=_ltgl9^v&LDgn)P zBGnu+Nj@T+uRRKmVvcr7O~YQ$SL}}@8(lAy(Mh>3`|KWQ z^vv*dKR2C82=@(=<4{o%W#aA8hedxJ#X`OLQ|IcQVndH_&{tXw%W_CoM|MnPnvrS@ zL_fdjAo;}y<(A3ZuYcV`mJCIt=>-D<3Wfc5hA;bnpc5)~RwlLerCVWq$W7CEv`uW7Gor<{kU@As7%2%zJ;dRT;k%b5JLY^?LY?J`BeAhYmQqdD^YxN0D~;n5G1<_;*$;u8g{B7EMT1i( z_?wn0-HGo>!?c-BmS-Yid29+RW(u3~--`gAWB6av%n~VjjF|oD#CV*grdp&ibs1Y) zxzjtN*44+DbUVCg(E^dyv7 z{J}z~UI`CG48+c=?{C!Xq0?;QNbjqEGT=ZObo1Z19bl;aUatbfAN0fK%eaLF1Yxq4 z(R!62yz3e(Ppll^jolM8(v&Ew6)VZ^iOU?V{_wQ-YCZy?e{XEj_a0E&(bAWw`CNTuE zSiS{zAoZCNf}H)(eGY%1CB6F5Tc2R75aGRe_tgFRdx>FTJXG#OM}m3i4xw^Uy9o{{ zf1H%uUl_BfB|b1`(7Zp=#(DcE5rU8VE{GaLdU(|E$tc#bQTd5%-}rf%>B78{B4Rfx z8KKctXZXc*a8vMz=OS1otivdBoetS)>c~XU`h&N|3zJ=>*`+-RI`;ix)q?%4@j1?NgUSEV_x%=mQux1xcydX2T`BErP_{$&nwUg%%K>R zYf?+4KxeGGn1!89#*~OHQ;&M;3BuH)s~^*J4?qeGDz{{-dias*ye@Hyq+$BI zKFyhpn>~L@b=>1d&8j+X=MmrU77%`Nj3JNknZVCPNyJJ#L`|#uM>0TwSk0 z`(Ab&Bs)<8uU$KVN+GIKV&_7CuwHp%e2eFH{DKBR&1hN)`Y@V$)77l=AeqXJ-iphu z@~Qoz-Y$EEZ$}^%!7W%~x+C}9)!?>KWGycF(v&1SnEF*er!}C^U_#-Hlo{-&TZPVn zfvQ+UZv_=anOKac4Sj8|Q z(!wqBDlaZ%)F{NBkdaZ`PG0jc)Jr8W8S0NT7rtjmC40$U4>(VCL+ME_>=h2376ey; zg?ne_$#akoW^VoU_gn;hGXa(TmdRj8QHEB}L9F}D{mIU5_8$x{@CHkv-XYMmrr;zf-Igdej|YooWssfGS>g#W9y`v9l1{~G{)P&N&FC1quEYzNu< z$jFRH$FXIvV`rsDk%&;r-Yeq?k&NsuWs7VMvdepVpXdEQ=N#kJ<9)BLuDGu5@8|x_ z`~IDC-@k9ZwqEgl=BLdi)Q@1kXP*erSXg807X z?s)v4v!EUbNFgbw_MF4E3GI5sIIvd6hQ5p9wT82j|C?UE{()LPUc~`XD$JP~z5NNz zPQ$Kx3+cdV7jKH(jd+(#=$$_xB;p0q1H2IefAV#yeOu)*s2$TI@W}8gRu7|Wm81|% z@gpxGD<_kw$2BymlQr)r;G(7|OK6IgO;e+>?v_e^G5$`)T7zDUA^Wo5=i6=Haz`nI z@i#L7zQT(%&LnhapZ^j4pgrZI^zvhBkF+5ha<_Xd?vY81YlSpWYOgx_hPdXCkqss$ z`r$YFMv=*-ynRM5i67yS?{cT9<9`8lj7T%ido<_rZuOCLt)0EXq|+%-JX3Lgw`I6N>xF&>a9#dj|&hT|fMNpQ)ztvl^|@fC_e1?Iu*yL*@V z5@^8T9=;c*V>Sod8q_F;okHyrLp(P~eoarJCF}U2i0Mg=o?;OpJAF|_!`rKtD^}2AptX`^cZ%g_ zX7TQ{AZBK@WZeY8WC1p#FXcBJrSNS(M=_Tu;Z}H#>MA}zv$=0>t{XzpA|?65d<3@a zH45L4*c_=|+0p6%luIoQ++Zmev`%f^(`Z!Fk4rGRmm3ZFvuCONX-g`8MfbBr^~KGF zglvW@dhnMXL#k7)dwNzgGl4n{B>W2nYo!C68TOXqmqXWu_1S|x`Kd!+Nfp3q+6}!_ zNEC7>3Ox9scoSIQhE_VB@X{UPunYD>u4i+xVlBY2mqpDzWGtl=T2gaX(+FaoQ!Bd( z++pJCIZwgJ<^9zErXHt-^U#lNGY=>qx5ch$^qd}hCvDkPd$68p{F%^k{G5S%Qy}f0 zo;;`;WjQ|08I_r_>Q`C?4@OGH(qjBYV8&hTk6ertEvp`r*2&xS7g$zb@oldmzojOZ z1RPT}sK3+$Vbyuld;Zm=fhdpVx8nAcY{pV*#mh?6O8vc^873}7Scbc#LyOp=(p$vX z7oBghbh5On7EcPQUrQ>ZESG}MM2K0K2X}`!+n5e6p=*1f{>kbei23a$~}}O3A|$Du(BIStLQ(Fwa^{wMeha zQAI?Z?5WA_bFJ6oT(yvDH>Mb{6|~R-eC|^oMV$oy93?a9Qu&Us$=GG$YmCK%XW@j+ zRoUMQBI>@{cg&P46!bSg6l;54y0E0SdG6feTgl<);7y{%;goTS+GhQyUaD>htPS__ zH7zvj3Um5G2|0**OTM>lK}<+xWLaro8_--P%Emxyn+97Qfj(;CU|JV)<&gkB{Hm<+ zZ$XT79(_)$?f30PQmb#y3Q7NP%fO>ky(Vt4#)3vg$=Fvprhe21bbo`R{%^SibB<2!g+N&@(JL2Iu`oTPZ4}deB zPhjba8TQB@^ty5j8(>oHSW^ngoO^qCSdw8cCWO2mkHs5g-eXXzSe3w%%)O;g{-@?* ztO0XDLfFloyOxY^-!N8ta_R*u?rJOtWpaE(51?nX-j*C+{x@yu02QGMk(T)krUL zjhvvZhhJdU8i~IrDy{AUY9`en1wU+OV*sg4!-{g#77Ht9pFa3dlN)zVK+0VUx3@iI z^t}=heQtE6q?_Bdd%5m}xasn|G($bExR@do;R`5XJ6i{QCQD?Vfiu_#P zOUo^B*NUrea=qTy5c<5ZFwoL5Pwu1^V{scMG~@~TiLus}{snBMYw6s}W-$1c6KG8) zkU-9Vb9!f$LqWNyHOxdbxL7!SJk#UleMh1_h9vW_^U)&ndedYk(*!95kiAGzb#ZpR z0nI0=->(y@PiQ@u?fGCDbFCnFEh|gXdQ1e=VYK{AAWUW}>74V6O4)R;LO;>t?7Q?zPcjC1qviMX{8K#3~vb8qR3PjP}QwRaaN&PLt1 zV=TC$>*GZ&G+cEn`PN>Me|`oq99&jBXOrpYQ(rT{7P>(m4(7csr{+CeBebIC;>v5g z>v?m-3{9ul(?a}9n?_i^-{_49R0%sIF$pQ!2!U>KWUk}NyJU93 zT^i{rpW`*+v~{`~F$2}M1-c*5WVA(;+r4x(caVr$gY*KyFax=GPMtSS?PW0wEkLlT z=cn26X^&psZ~~!aNbfP^#K2GYe78`jk2>z)xl&k3B;2w3Yw6<(PDn!H8ytG$En`A^X-a1aAwbcZ+ z%EiE+B2_Z>btu+N9GL&AG&NX*fWpmHlNFIEDX zSKqkktY-#ztHsb1NvFogq?Sd9dJElUE)sJB0=tsTL8;Qlk@WJ6viZzSrTpxPn}4(KnX|lSG{@NY?vkCoQ&VTXt4ox5KoFWGn;HW2_=->2G`P7^pcyDWIm^e&sd8Ale~wNvt@WWD-{#BIa z!d4q`ywKihCR55Lz(>p6z?5nwqXev8vQX*5wpjoz|TFO*G ze6_J1Z;GM2cTY6&u5H3+?Yfr2SNfD?Ks&1!b<;zAtYWDOPmBVxx!Nt8>}DYpQ-y{* zy;)*}gOgfmPgli=W@9mKl7K(CYmd&%8}Q;>s@zJh_La}nnDPvG;rBgF}}R{VP@a^J?)3;I;FPy&3c+|_LOc+ zR~DlmP^r)vZ;$V%btg9mlwmFj-|)p&(BNOmgtOO|tNH|*HhF3{tLx3%O|hF^!az0BQbTvBP!y7~S) zBO&voA=x1r)(`9|m-#xPHooqbJfhAa>Q{sJuz&bNFcNs_ z)4ZcSGw?0%msFL=NQvr2Ue2Bgf6xPW`XuB??Y7A>G0V3>ulhkDVBo@c(GV{Y4@rL? z6KsW!J2{tdp1{MXgr7P%U>id~B7w6e35xRVV~c^d9i}dZRLh=cTB2;B@FY=CcxxtA zrLI0LoO5IeXV+)O-4FNKhp()KtrJ#y9~`2aBD$6x78(P~LxkYGUvDsKHorCZtnm`? z!Io^v&vu~jAzn`R-5hh=14ZW4ao=afxkaDh_~TCKDqqw5m_F=9umh&reV;H|jD~&M zE6yh5$sw2)J|gbktnT7`^clCq_UB$v+JKmfah?zPI=s~qR#Yq{`sPW& z6DXW&9An2RpuOPQSXaiuE1_NOyPYXeN&-j z-5tN~$4xzJyxb#pm8DSo<4)9A@;|h(LlK0>^ zP_jJBdc<>6vNdH7*9O$w3nM&>Z4$*({rqw@4t>3sLzL7GC6jn7**S-G#J%t%k}xgz zNTI0M6;k5{5g3{JZZhXqhi+YGR@dlm^3B(rTR87Xssnt#W+at*Q|*7ar(iLzrTWR2 zAvKYr-?#ocuLe{n|)yuEQP+)Mf7B#JiPIn2sh>=Z=3?zj9VWutSpF zyi`#rj}d=D-%3g|O#-yL!3u0y8R+2Yv}n2if-sUYwULYK75tBA?p=v~N7$w8^NDpB z64k>sko~~r`+a*10i-wkT#57lNT}UUYS{J%Y6?+$7_3L`l&%}6x&Bb}zA{XuBq;Z} z<)TUqWN<;=*V6!{*5AJ@Us&MT0d->*FO;eSgEymqw z^T8Q~91X$k=ONU#8-~|k+hpQb14(mOUI|S3jD&dV6HIoc4^o5*V+p|R>6XS2mp9O^K0#efk}#m4*=i-4tzL-_n)860~UX!a{#ExX-jb` zf#tdXI_#g%l)7o;+zk-_!22`-etf1D^V%0}47#AZc_ zJ$Rzne?MZ1HhP@Sb~xjn0RZBN0RTZHA;q5_>v!5t>c9W}>yr><<5zX#GpMjFBL+R@ zB>+GI#R$jweM1&v1A&@4Lk_o8+JBT269NEb^Z)=aiZxAk66=@Y`cEb#^ziRBM&E(4 z0f4S^0DvS)c&#hH)g@&i=9YGlzxR=HIvmS*Z`(M5Xj@Ed^s*3NI|(L(s5EC&JLe<9 z+tX8g4Ma4u8xDF|)HzNPUe?3T)Yj5W$JEi%^o|YW*JC9%|4CMdjy>e`iN!@=v52yO zP%ufJlVEapEfI}!ghYskUaUgkZw>Ch8%Oc4-w(%ZO3fn# z5RfeuI@Tuiy954j?^hb4gV?XJDl)c2LW}6d=lKyAPZZ2v>J%8FE1J64ILp}E*g%dM z#a?yHZZ?Q|EkJY^1r!}m_cXetsf|69k@s*kD46)l1Y)vhI)jeR8Jr&FI~+|`HFg|A zpo|AlDWlV)z{Am&SWB88h)Fo?DgYpdf=1mwHF|h|BF0k!KSj(hmk?u8ABDuUKLz=} zWtT%gjs4pkq{WCa^nnrpkVQF-OOB^Kjl=8O$JGDs0-}M}5#3oDMU;X4OVR1qHr7Y= z;n$nHPRqzlLrUg%Y1Mu?}*VEcmBQjcSQN9u+csKh*Np|hkIxC{Me@uJ!a)V z4~>gFl_zkxC&J?R^_RDFz*~B9Do^lmkKYl)aO&?7fi?nTPUQ(5?p=g4UYb0#KA$~1 zl_z|-7j;ot=^Mg>AMobmPvwam?)5~j6#F3N<o_$aNG?I`K5#;aY4XNtFv?S%P&D z{jP_r^mjESJ4?Z%SKa6a))0+$9dX@P zL6HVO{#yxg5AF=Hb4Jagjt)<10T-DOJ*654{R$}8`fuUm@2fyzn#^AjMcu(d7l%7e zDIPIn*RX}(8bgR%2Si}^Da9k^Y`AbF@%W))Q12DIPI*lVdl&Sw#$f9$ECcv}62q z;^FtB$SK{GP(0qff9t85-htR0KM5cweU?ID-|YV%WRFMZkTdD(pm6wSF#ezNN~50x zat=AvA~WKg>KwIOYfuwc6y5+S$V-$I#ex;Z3R=QLLyo-CXAUjpaI~Y_Rr`_ctZRMr)~pkGc-M_uN%vIG-WKcK?mP!2-jx@$p5;sL z-F%|a>!O_|YOH&XFI`FRKNg(JK)L^P+V+N=?zZTC$8~o#YkxN0apOvMceUy-_~Es7 zLS+_i-6I{YwCbN$-$%$q8aHGO}rGj)+ z=KJz5`wjkbBFYrV5-ZnIF=?i!#3|V*v!buC21nD&Uyx7 zV`GCj*ECUFUHnG$#hywN1OYDz&)s9WqdPB78Bi-RO6P~mV zt4MHQOkY-QpYq4v)d~IaO$S}p+sWB?7h=uNbH}sKt}7CXCic5~RQ{dDxOH&*zLkfT zZOAw`ZDRc|n@XK_)pcR{eW!2ow-QO(d7|n0R2qWBTOcozRCjWwNgDsgPEL+vauipJ zQAJJ**S67*fn3NLm+|Dn_Z|h~7j?5k-Hy{r?KI7GZ?VS&FtS&iv^bTDjx?vt7X-1WpugN;%rr zGJb01)_|rH_2ug-&+>As9^VW1^51i)%=O1Sw;cEO$66W@k^<~NT|PLx19l9LX2Gx= z`sNOU_qyeT^stC0!#&o)jIoUB+rp2BD3?H#8F~=$p;1jD!y;Kx+%V4kSY~7xS@`s( zo0NO>mVto~J`22JAtqD6O(%@isV1XIGcO3xm_~RT2C6Ow458X%zz{%8g7VYFXa-Xx zP9k%Nfuqx*otXjH9N3N&4z1;Yt`L)FnPMGlh2gw1uR~3sG!OKhDcGG>WGo*|6e~>$ z2=T|)x*GF65drGMl0 zY)%9#Dx5Q)8M`Q!Ts;VeKWjhq&!;X*iJ%h&?6F2vmj$a5Hd%MpciA7S*Y=X6VThHQ2m5vmg3z3i=o!^utrbO zISD4~)CVXG70WEydla$-uO>5$aK=XRXt_2b_`5#aUp;|Cw_EHxgAS z1R_+yH1>RRiAp`ZS$+tj6yPFMsrT5}T*-4b}KSLNCDy|ljlTY zjvrVW)$uo?ub=A41%;?&8Kzy|o#sIt}nKgh2R17QX^UFk1oFHgi1afFhiE`|nz F{0pBN2HOAt literal 0 HcmV?d00001 diff --git a/site/updates/testing/2.0/compositeArtifacts.xml b/site/updates/testing/2.0/compositeArtifacts.xml index 2a44a521..02fc728c 100644 --- a/site/updates/testing/2.0/compositeArtifacts.xml +++ b/site/updates/testing/2.0/compositeArtifacts.xml @@ -2,11 +2,10 @@ - + - - - + + diff --git a/site/updates/testing/2.0/compositeContent.xml b/site/updates/testing/2.0/compositeContent.xml index c20f2b11..3c75b324 100644 --- a/site/updates/testing/2.0/compositeContent.xml +++ b/site/updates/testing/2.0/compositeContent.xml @@ -2,11 +2,10 @@ - + - - - + + From 8a1880db91f8f608ef34517bcc89ee9ee8898897 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Wed, 20 Jul 2016 22:29:16 +0200 Subject: [PATCH 17/73] #65 [v2.0] edit of command does only change the menu but not the command itself Signed-off-by: Andre Bossert --- .../plugin/preferences/CommandDataStore.java | 19 ++++++++++++------- .../plugin/preferences/MenuDataDialog.java | 11 +++++++---- .../plugin/preferences/MenuDataStore.java | 10 +++++----- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataStore.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataStore.java index 6d8c6f76..703caa46 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataStore.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataStore.java @@ -69,7 +69,7 @@ public CommandData[] getAllCommandsArray() { } public CommandData getPreviousElement(CommandData data) { - sort(items); + sort(); for(int i = 0 ; i < items.size() ; i++) { CommandData item = (CommandData)items.get(i); if(item.equals(data)) { @@ -84,7 +84,7 @@ public CommandData getPreviousElement(CommandData data) { } public CommandData getNextElement(CommandData data) { - sort(items); + sort(); for(int i = 0 ; i < items.size() ; i++) { CommandData item = (CommandData)items.get(i); if(item.equals(data)) { @@ -99,7 +99,7 @@ public CommandData getNextElement(CommandData data) { } public CommandData getLastElement() { - sort(items); + sort(); int index = items.size() - 1; if(index < 0) { return null; @@ -115,12 +115,17 @@ public void add(CommandData data) { } data.setPosition(position); items.add(data); - sort(items); + sort(); + } + + public void replace(CommandData data) { + items.set(data.getPosition(), data); + //sort(); } public void delete(CommandData data) { items.remove(data); - sort(items); + sort(); } public void save() { @@ -144,7 +149,7 @@ public void load() { for(int i = 0 ; i < arrayUser.length ; i++) { this.items.add(arrayUser[i]); } - sort(items); + sort(); } public void removeAll() { @@ -164,7 +169,7 @@ public CommandData getCommandDataByPosition(int position) { return items.get(position); } - private void sort(List items) { + private void sort() { if(comparator == null) { comparator = new DataObjectComparator(); } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java index 549341eb..bfd6869b 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java @@ -250,6 +250,13 @@ private void addCommand(CommandData data) { commandCombo.select(names.length-1); } + private void replaceCommand(int index, CommandData data) { + cmdStore.replace(data); + cmdStore.save(); + commandCombo.setItem(index, getCommandAsComboName(data)); + commandCombo.select(index); + } + private void removeCommand(int index, CommandData data) { cmdStore.delete(data); cmdStore.save(); @@ -301,10 +308,6 @@ private void removeDialog() { } } - private void replaceCommand(int index, CommandData data) { - commandCombo.setItem(index, getCommandAsComboName(data)); - } - private void refreshCommandCombo() { // send event to refresh Event event = new Event(); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java index 64484e30..42405de5 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java @@ -122,13 +122,13 @@ public void add(MenuData data) { sort(); } - public void delete(MenuData data) { - items.remove(data); - sort(); - } - public void replace(MenuData data) { items.set(data.getPosition(), data); + //sort(); + } + + public void delete(MenuData data) { + items.remove(data); sort(); } From 1f9a8e5d87c96b87eb3c6ba34f3fe591357cfb94 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Thu, 21 Jul 2016 16:25:30 +0200 Subject: [PATCH 18/73] #66 add support for setting working directory before executing a command - new store format - refactoring of store migration Signed-off-by: Andre Bossert --- .../eclipse/easyshell/plugin/Activator.java | 3 +- .../eclipse/easyshell/plugin/Constants.java | 7 - .../easyshell/plugin/UIMessages.properties | 6 +- .../plugin/actions/ActionDelegate.java | 185 ++++++++++-------- .../plugin/commands/DefineCommands.java | 9 +- .../plugin/handlers/CommandHandler.java | 6 +- .../plugin/preferences/CommandData.java | 99 +++++++--- .../CommandDataDefaultCollection.java | 2 +- .../plugin/preferences/CommandDataDialog.java | 96 +++++++-- .../plugin/preferences/Initializer.java | 25 +-- .../plugin/preferences/MenuData.java | 84 ++++---- .../plugin/preferences/MenuDataDialog.java | 2 +- .../preferences/MenuDataLabelProvider.java | 2 +- .../preferences/PreferenceValueConverter.java | 18 +- .../easyshell/plugin/types/CommandType.java | 9 +- .../eclipse/easyshell/plugin/types/Debug.java | 9 +- .../easyshell/plugin/types/LinuxDesktop.java | 9 +- .../easyshell/plugin/types/MenuNameType.java | 9 +- .../eclipse/easyshell/plugin/types/OS.java | 9 +- .../easyshell/plugin/types/PresetType.java | 9 +- .../easyshell/plugin/types/Quotes.java | 9 +- .../easyshell/plugin/types/ResourceType.java | 9 +- .../easyshell/plugin/types/Tokenizer.java | 9 +- .../easyshell/plugin/types/Version.java | 68 +++++++ 24 files changed, 411 insertions(+), 282 deletions(-) create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/types/Version.java diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java index 76cf6d3f..3a228170 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java @@ -33,6 +33,7 @@ import de.anbos.eclipse.easyshell.plugin.types.CommandType; import de.anbos.eclipse.easyshell.plugin.types.Debug; +import de.anbos.eclipse.easyshell.plugin.types.Version; /** * The activator class controls the plug-in life cycle @@ -225,7 +226,7 @@ public static void logDebug(String string) { public IPreferenceStore getPreferenceStore() { // Create the preference store lazily. if (myPreferenceStore == null) { - myPreferenceStore = getNewPreferenceStoreByVersion(Constants.PREF_VERSIONS[0]); + myPreferenceStore = getNewPreferenceStoreByVersion(Version.actual.name()); } return myPreferenceStore; } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/Constants.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/Constants.java index a1fa0ebe..66cc1571 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/Constants.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/Constants.java @@ -26,13 +26,6 @@ public interface Constants { public static final String IMAGE_OTHER = "editor.gif"; // Preferences - // version with index = 0 is the actual one - // do not delete old entries !!! - public static final String[] PREF_VERSIONS = { - "v2_0_002", - "v2_0_001", - "v1_4" - }; public static final String PREF_COMMANDS_PRESET = "COMMANDS_PRESET"; public static final String PREF_COMMANDS = "COMMANDS"; public static final String PREF_MENU = "MENU"; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties index 015753b5..ba536484 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties @@ -64,12 +64,16 @@ easyshell.command.editor.dialog.title.group1=Command easyshell.command.editor.dialog.tooltip.group1=Add your command here easyshell.command.editor.dialog.title.group2=Usable variables easyshell.command.editor.dialog.tooltip.group2=Double click at variable copies it to clipboard -easyshell.command.editor.dialog.error.title.incompletedata=Missing or wrong command detected +easyshell.command.editor.dialog.error.title.incompletedata=Missing or wrong parameters easyshell.command.editor.dialog.error.text.resource=Please choose a valid resource type easyshell.command.editor.dialog.error.text.type=Please choose a valid command type easyshell.command.editor.dialog.error.text.name=Please enter a valid name +easyshell.command.editor.dialog.error.text.workingdir=Please enter a valid working directory easyshell.command.editor.dialog.error.text.value=Please enter a valid command easyshell.command.editor.dialog.label.combo1=type: easyshell.command.editor.dialog.label.combo2=resource: easyshell.command.editor.dialog.label.name=name: +easyshell.command.editor.dialog.label.useworkdir=working directory: +easyshell.command.editor.dialog.button.tooltip.useworkdir=Set working directory prior command execution?\n\nNeeded for commands that does not support working directory as parameter. +easyshell.command.editor.dialog.label.workdir= easyshell.command.editor.dialog.label.value=command: diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java index a47ffc9d..d2b7a397 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/ActionDelegate.java @@ -11,6 +11,8 @@ package de.anbos.eclipse.easyshell.plugin.actions; +import java.io.File; +import java.io.IOException; import java.util.StringTokenizer; import org.eclipse.core.runtime.CoreException; @@ -36,6 +38,7 @@ public class ActionDelegate implements IObjectActionDelegate { private Resource[] resource = null; private IStructuredSelection currentSelection; private String commandValue = null; + private String commandWorkingDir = null; private CommandType commandType = CommandType.commandTypeUnknown; public CommandType getCommandType() { @@ -54,6 +57,10 @@ public void setCommandValue(String commandValue) { this.commandValue = commandValue; } + public void setCommandWorkingDir(String commandWorkingDir) { + this.commandWorkingDir = commandWorkingDir; + } + public ActionDelegate() { super(); } @@ -66,68 +73,26 @@ public void run(IAction action) { Activator.logError("Wrong Selection", null); return; } - - /* TODO: remove - // get the ID - String ActionIDStr = action.getId(); - Activator.logDebug("Action ID: >" + ActionIDStr + "<"); - */ - // String for all commands in case of clipboard String cmdAll = null; if (commandType == CommandType.commandTypeClipboard) { cmdAll = new String(); } - + // get the manager for variables expansion IStringVariableManager variableManager = VariablesPlugin.getDefault().getStringVariableManager(); - + // iterate over the reources for (int i=0;i" + full_path + "<"); - Activator.logDebug("parent_path: >" + parent_path + "<"); - Activator.logDebug("file_name : >" + file_name + "<"); - - // Try to extract drive on Win32 - if (full_path.indexOf(":") != -1) { - drive = full_path.substring(0, full_path.indexOf(":")); - } - + // TODO: get from preferences store + //Quotes quotes = Activator.getQuotes(InstanceIDNum); + Quotes quotes = Quotes.quotesNo; + String[] args = fillArguments(resource[i], variableManager, quotes); + if (args != null) { try { - // TODO: get from preferences store - //Quotes quotes = Activator.getQuotes(InstanceIDNum); - Quotes quotes = Quotes.quotesNo; - String[] args = new String[6]; - // args format - args[0] = drive; // {0} == ${easyshell:drive} - args[1] = autoQuotes(parent_path, quotes); // {1} == ${easyshell:container_loc} - args[2] = autoQuotes(full_path, quotes); // {2} == ${easyshell:resource_loc} - args[3] = autoQuotes(file_name, quotes); // {3} == ${easyshell:resource_name} - args[4] = resource[i].getProjectName(); // {4} == ${easyshell:project_name} - if (args[4] == null) - args[4] = Activator.getResourceString("easyshell.plugin.name"); - args[5] = System.getProperty("line.separator"); // {5} == ${easyshell:line_separator} - // variable format + // set arguments for resolving DynamicVariableResolver.setArgs(args); + // validate the command variableManager.validateStringVariables(commandValue); Activator.logDebug(commandValue); // handling copy to clipboard @@ -140,46 +105,17 @@ public void run(IAction action) { } // handling command line else { - // string tokenizer enabled ? - // TODO: get from preferences store - //Tokenizer tokenizer = Activator.isTokenizer(InstanceIDNum); - Tokenizer tokenizer = Tokenizer.tokenizerYes; - if (tokenizer == Tokenizer.tokenizerYes) - { - StringTokenizer st = new StringTokenizer(commandValue); - String[] cmds = new String[st.countTokens()]; - int c = 0; - Activator.logDebug("--- cmd: >"); - while (st.hasMoreElements()) { - cmds[c] = fixQuotes(variableManager.performStringSubstitution(st.nextToken(), false), quotes); - Activator.logDebug(cmds[c]); - c++; - } - Activator.logDebug("--- cmd: <"); - //Utils.showToolTip(Display.getDefault().getActiveShell(), "EasyShell: executed", commandValue); - // ---------- RUN -------------- - Runtime.getRuntime().exec(cmds); - } - // the old command line passing without string tokenizer - else { - String cmd = fixQuotes(variableManager.performStringSubstitution(commandValue, false), quotes); - Activator.logDebug("--- cmd: >"); - Activator.logDebug(cmd); - Activator.logDebug("--- cmd: <"); - Runtime.getRuntime().exec(cmd); - } + handleExec(variableManager, quotes); } } catch (CoreException e) { Activator.logError(Activator.getResourceString("easyshell.message.error.validation"), commandValue, e, true); } catch (Exception e) { Activator.logError(Activator.getResourceString("easyshell.message.error.execution"), commandValue, e, true); } - } else { Activator.logError(Activator.getResourceString("easyshell.message.error.internal"), commandValue, null, true); } } - // handling copy to clipboard if ((commandType == CommandType.commandTypeClipboard) && (cmdAll != null) && (cmdAll.length() != 0)) { Utils.copyToClipboard(cmdAll); @@ -187,6 +123,93 @@ public void run(IAction action) { } } + private String[] fillArguments(Resource res, IStringVariableManager variableManager, Quotes quotes) { + String[] args = null; + String drive = null; + String full_path = null; + String parent_path = null; + String file_name = null; + full_path = res.getFile().toString(); + if (res.getFile().isDirectory()) { + parent_path = res.getFile().getPath(); + //file_name = "dir"; // dummy cmd + } else { + parent_path = res.getFile().getParent(); + file_name = res.getFile().getName(); + } + if (full_path != null) { + Activator.logDebug("full_path : >" + full_path + "<"); + Activator.logDebug("parent_path: >" + parent_path + "<"); + Activator.logDebug("file_name : >" + file_name + "<"); + // Try to extract drive on Win32 + if (full_path.indexOf(":") != -1) { + drive = full_path.substring(0, full_path.indexOf(":")); + } + String project_name = res.getProjectName(); + if (project_name == null || project_name.isEmpty()) { + project_name = Activator.getResourceString("easyshell.plugin.name"); + } + String line_separator = System.getProperty("line.separator"); + // args format + args = new String[6]; + args[0] = drive; // {0} == ${easyshell:drive} + args[1] = autoQuotes(parent_path, quotes); // {1} == ${easyshell:container_loc} + args[2] = autoQuotes(full_path, quotes); // {2} == ${easyshell:resource_loc} + args[3] = autoQuotes(file_name, quotes); // {3} == ${easyshell:resource_name} + args[4] = project_name; // {4} == ${easyshell:project_name} + args[5] = line_separator; // {5} == ${easyshell:line_separator} + } + return args; + } + + private void handleExec(IStringVariableManager variableManager, Quotes quotes) throws CoreException, IOException { + String[] cmds = null; + // working directory + if (commandWorkingDir != null && !commandWorkingDir.isEmpty()) { + variableManager.validateStringVariables(commandWorkingDir); + } + Activator.logDebug(commandWorkingDir); + // string tokenizer enabled ? + // TODO: get from preferences store + //Tokenizer tokenizer = Activator.isTokenizer(InstanceIDNum); + Tokenizer tokenizer = Tokenizer.tokenizerYes; + if (tokenizer == Tokenizer.tokenizerYes) + { + StringTokenizer st = new StringTokenizer(commandValue); + cmds = new String[st.countTokens()]; + int i = 0; + while (st.hasMoreElements()) { + cmds[i] = fixQuotes(variableManager.performStringSubstitution(st.nextToken(), false), quotes); + i++; + } + } + // the old command line passing without string tokenizer + else { + cmds = new String[1]; + cmds[0] = fixQuotes(variableManager.performStringSubstitution(commandValue, false), quotes); + } + // log out + for (int i=0;i"); + Activator.logDebug(cmds[i]); + Activator.logDebug("--- cmd: <"); + } + // execute + //Utils.showToolTip(Display.getDefault().getActiveShell(), "EasyShell: executed", commandValue); + // ---------- RUN -------------- + //Runtime.getRuntime().exec(cmds); + // create process builder with commands and + ProcessBuilder pb = new ProcessBuilder(cmds); + // set working directory and redirect error stream + if (commandWorkingDir != null && !commandWorkingDir.isEmpty()) { + pb.directory(new File(variableManager.performStringSubstitution(commandWorkingDir, false))); + } + // get passed system environment + //Map env = pb.environment(); + // add own variables + pb.start(); + } + public void selectionChanged(IAction action, ISelection selection) { currentSelection = selection instanceof IStructuredSelection ? (IStructuredSelection)selection : null; } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java index 7c6e33af..2bf0bede 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java @@ -44,22 +44,25 @@ public void createContributionItems(IServiceLocator serviceLocator, item.getNameExpanded(), "de.anbos.eclipse.easyshell.plugin.commands.execute", "de.anbos.eclipse.easyshell.plugin.commands.parameter.type", - item.getCommandData().getTypeAction(), + item.getCommandData().getCommandType().getAction(), "de.anbos.eclipse.easyshell.plugin.commands.parameter.value", item.getCommandData().getCommand(), - item.getCommandData().getTypeIcon()); + "de.anbos.eclipse.easyshell.plugin.commands.parameter.workingdir", + item.getCommandData().isUseWorkingDirectory() ? item.getCommandData().getWorkingDirectory() : "", + item.getCommandData().getCommandType().getIcon()); } } private void addItem(IServiceLocator serviceLocator, IContributionRoot additions, String commandLabel, String commandId, - String paramId1, String paramValue1, String paramId2, String paramValue2, String commandImageId) { + String paramId1, String paramValue1, String paramId2, String paramValue2, String paramId3, String paramValue3, String commandImageId) { CommandContributionItemParameter param = new CommandContributionItemParameter(serviceLocator, "", commandId, SWT.PUSH); param.label = commandLabel; param.icon = Activator.getImageDescriptor(commandImageId); Map commandParamametersMap = new HashMap(); commandParamametersMap.put(paramId1, paramValue1); commandParamametersMap.put(paramId2, paramValue2); + commandParamametersMap.put(paramId3, paramValue3); param.parameters = commandParamametersMap; CommandContributionItem item = new CommandContributionItem(param); item.setVisible(true); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/CommandHandler.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/CommandHandler.java index bb00284a..b7e58581 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/CommandHandler.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/CommandHandler.java @@ -31,9 +31,11 @@ public Object execute(ExecutionEvent event) throws ExecutionException { if (action != null) { String commandID = event.getCommand().getId(); String commandType = event.getParameter("de.anbos.eclipse.easyshell.plugin.commands.parameter.type"); - String commanValue = event.getParameter("de.anbos.eclipse.easyshell.plugin.commands.parameter.value"); + String commandValue = event.getParameter("de.anbos.eclipse.easyshell.plugin.commands.parameter.value"); + String commandWorkingDir = event.getParameter("de.anbos.eclipse.easyshell.plugin.commands.parameter.workingdir"); action.setCommandType(CommandType.getFromAction(commandType)); - action.setCommandValue(commanValue); + action.setCommandValue(commandValue); + action.setCommandWorkingDir(commandWorkingDir); Action act = new Action(commandID); action.run((IAction)act); } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java index 509abc0e..3c79e3ab 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java @@ -18,21 +18,25 @@ import de.anbos.eclipse.easyshell.plugin.types.OS; import de.anbos.eclipse.easyshell.plugin.types.PresetType; import de.anbos.eclipse.easyshell.plugin.types.ResourceType; +import de.anbos.eclipse.easyshell.plugin.types.Version; public class CommandData { // internal private int position = 0; private String id = null; + // command private PresetType presetType = PresetType.presetUnknown; private OS os = OS.osUnknown; - private String name = null; - private ResourceType resType = ResourceType.resourceTypeUnknown; - private CommandType cmdType = CommandType.commandTypeUnknown; - private String command = null; - - public CommandData(String id, PresetType presetType, OS os, String name, ResourceType resType, CommandType cmdType, String command) { + private String name = ""; + private ResourceType resourceType = ResourceType.resourceTypeUnknown; + private boolean useWorkingDirectory = false; + private String workingDirectory = ""; + private CommandType commandType = CommandType.commandTypeUnknown; + private String command = ""; + + public CommandData(String id, PresetType presetType, OS os, String name, ResourceType resType, boolean useWorkingDirectory, String workingDirectory, CommandType cmdType, String command) { if (id == null || id.isEmpty()) { this.id = UUID.randomUUID().toString(); } else { @@ -41,19 +45,19 @@ public CommandData(String id, PresetType presetType, OS os, String name, Resourc this.presetType = presetType; this.os = os; this.name = name; - this.resType = resType; - this.cmdType = cmdType; + this.resourceType = resType; + this.useWorkingDirectory = useWorkingDirectory; + this.workingDirectory = workingDirectory; + this.commandType = cmdType; this.command = command; } + public CommandData(String id, PresetType presetType, OS os, String name, ResourceType resType, CommandType cmdType, String command) { + this(id, presetType, os, name, resType, false, "${easyshell:container_loc}", cmdType, command); + } + public CommandData(CommandData commandData, String newId) { - this.id = newId; - this.presetType = commandData.getPresetType(); - this.os = commandData.getOS(); - this.name = commandData.getName(); - this.resType = commandData.getResourceType(); - this.cmdType = commandData.getCommandType(); - this.command = commandData.getCommand(); + this(newId, commandData.getPresetType(), commandData.getOs(), commandData.getName(), commandData.getResourceType(), commandData.isUseWorkingDirectory(), commandData.getWorkingDirectory(), commandData.getCommandType(), commandData.getCommand()); } public CommandData(CommandData commandData, boolean generateNewId) { @@ -75,7 +79,7 @@ public String getName() { return name; } - public OS getOS() { + public OS getOs() { return os; } @@ -84,11 +88,19 @@ public PresetType getPresetType() { } public ResourceType getResourceType() { - return resType; + return resourceType; + } + + public boolean isUseWorkingDirectory() { + return useWorkingDirectory; + } + + public String getWorkingDirectory() { + return workingDirectory; } public CommandType getCommandType() { - return cmdType; + return commandType; } public String getCommand() { @@ -116,11 +128,19 @@ public void setPresetType(PresetType presetType) { } public void setResourceType(ResourceType resType) { - this.resType = resType; + this.resourceType = resType; + } + + public void setUseWorkingDirectory(boolean useWorkingDirectory) { + this.useWorkingDirectory = useWorkingDirectory; + } + + public void setWorkingDirectory(String workingDirectory) { + this.workingDirectory = workingDirectory; } public void setCommandType(CommandType cmdType) { - this.cmdType = cmdType; + this.commandType = cmdType; } public void setCommand(String command) { @@ -147,7 +167,7 @@ public boolean equals(Object object) { return false; } - public boolean deserialize(String value, StringTokenizer tokenizer, String delimiter) { + public boolean deserialize(Version version, String value, StringTokenizer tokenizer, String delimiter) { if((value == null || value.length() <= 0) && tokenizer == null) { return false; } @@ -162,25 +182,42 @@ public boolean deserialize(String value, StringTokenizer tokenizer, String delim setOs(OS.getFromEnum(tokenizer.nextToken())); setName(tokenizer.nextToken()); setResourceType(ResourceType.getFromEnum(tokenizer.nextToken())); + // handling of working directory + if (version.getId() >= Version.v2_0_003.getId()) { + setUseWorkingDirectory(Boolean.valueOf(tokenizer.nextToken()).booleanValue()); + setWorkingDirectory(tokenizer.nextToken()); + } else { + setUseWorkingDirectory(false); + setWorkingDirectory("${easyshell:container_loc}"); + } + // go on compatible setCommandType(CommandType.getFromEnum(tokenizer.nextToken())); setCommand(tokenizer.nextToken()); return true; } - public boolean deserialize_v2_0_001(String value, StringTokenizer tokenizer, String delimiter) { - return deserialize(value, tokenizer, delimiter); + public boolean deserialize(String value, StringTokenizer tokenizer, String delimiter) { + return deserialize(Version.actual, value, tokenizer, delimiter); } - public String serialize(String delimiter) { - return Integer.toString(getPosition()) + delimiter + getId() + delimiter + getPresetType().toString() + delimiter + getOS().toString() + delimiter + getName() + delimiter + getResourceType().toString() + delimiter + getCommandType().toString() + delimiter + getCommand() + delimiter; - } - - public String getTypeIcon() { - return getCommandType().getIcon(); + public String serialize(Version version, String delimiter) { + String ret = Integer.toString(getPosition()) + delimiter; + ret += getId() + delimiter; + ret += getPresetType().toString() + delimiter; + ret += getOs().toString() + delimiter; + ret += getName() + delimiter; + ret += getResourceType().toString() + delimiter; + if (version.getId() >= Version.v2_0_003.getId()) { + ret += Boolean.toString(isUseWorkingDirectory()) + delimiter; + ret += getWorkingDirectory() + delimiter; + } + ret += getCommandType().toString() + delimiter; + ret += getCommand() + delimiter; + return ret; } - public String getTypeAction() { - return getCommandType().getAction(); + public String serialize(String delimiter) { + return serialize(Version.actual, delimiter); } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java index 669670d9..5e0be1f1 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java @@ -221,7 +221,7 @@ public static List getCommandData(List list, OS os, bo List listOut = new ArrayList(); int position = 0; for (CommandData entry : list) { - if (entry.getOS() == os) { + if (entry.getOs() == os) { CommandData newData = new CommandData(entry, false); if (sorted) { newData.setPosition(position); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java index 603ecf86..03b26390 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java @@ -21,6 +21,7 @@ import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; @@ -42,6 +43,8 @@ public class CommandDataDialog extends StatusDialog { private Combo resourceTypeCombo; private Combo commandTypeCombo; private Text nameText; + private Button dirCheckBox; + private Text dirText; private Text valueText; public CommandDataDialog(Shell parent, CommandData data, boolean edit) { @@ -81,7 +84,7 @@ public Control createDialogArea(Composite parent) { pageGroup1.setText(Activator.getResourceString("easyshell.command.editor.dialog.title.group1")); pageGroup1.setToolTipText(Activator.getResourceString("easyshell.command.editor.dialog.tooltip.group1")); GridLayout layout1 = new GridLayout(); - layout1.numColumns = 2; + layout1.numColumns = 3; layout1.makeColumnsEqualWidth = false; layout1.marginWidth = 5; layout1.marginHeight = 4; @@ -94,9 +97,12 @@ public Control createDialogArea(Composite parent) { // create command type combo createCommandTypeCombo(pageGroup1); //create input nameText field - nameText = createTextField(pageGroup1, Activator.getResourceString("easyshell.command.editor.dialog.label.name"), data.getName()); + nameText = createTextField(pageGroup1, Activator.getResourceString("easyshell.command.editor.dialog.label.name"), data.getName(), true); + // create directory checkbox + createDirCheckBox(pageGroup1); + dirText = createTextField(pageGroup1, null, data.getWorkingDirectory(), false); // create input valueText field - valueText = createTextField(pageGroup1, Activator.getResourceString("easyshell.command.editor.dialog.label.value"), data.getCommand()); + valueText = createTextField(pageGroup1, Activator.getResourceString("easyshell.command.editor.dialog.label.value"), data.getCommand(), true); // ------------------------------------ Description ------------------------------------------ // define group2 @@ -113,21 +119,53 @@ public Control createDialogArea(Composite parent) { pageGroup2.setLayoutData(data2); pageGroup2.setFont(parent.getFont()); - createLabel(pageGroup2, "${easyshell:drive}", "is the drive letter on Win32"); - createLabel(pageGroup2, "${easyshell:container_loc}", "is the parent path*"); - createLabel(pageGroup2, "${easyshell:resource_loc}", "is the full path*"); - createLabel(pageGroup2, "${easyshell:resource_name}", "is the file name*"); - createLabel(pageGroup2, "${easyshell:project_name}", "is the project name"); - createLabel(pageGroup2, "${easyshell:line_separator}", "is the line separator"); + createVariableLabel(pageGroup2, "${easyshell:drive}", "is the drive letter on Win32"); + createVariableLabel(pageGroup2, "${easyshell:container_loc}", "is the parent path*"); + createVariableLabel(pageGroup2, "${easyshell:resource_loc}", "is the full path*"); + createVariableLabel(pageGroup2, "${easyshell:resource_name}", "is the file name*"); + createVariableLabel(pageGroup2, "${easyshell:project_name}", "is the project name"); + createVariableLabel(pageGroup2, "${easyshell:line_separator}", "is the line separator"); refreshResourceTypeCombo(); + refreshDirCheckBox(); + refreshCommandTypeCombo(); return pageComponent; } - private void createLabel(Composite parent, String varText, String labelText) { + private void createLabel(Composite parent, String name) { + Label label = new Label(parent, SWT.LEFT); + label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END)); + label.setText(name); + } + + private void createDirCheckBox(Composite parent) { + // draw label + createLabel(parent, Activator.getResourceString("easyshell.command.editor.dialog.label.useworkdir")); + // draw checkbox + dirCheckBox = new Button(parent,SWT.CHECK); + dirCheckBox.setSelection(this.data.isUseWorkingDirectory()); + dirCheckBox.addSelectionListener(new SelectionListener() { + @Override + public void widgetSelected(SelectionEvent e) { + //Button button = (Button)e.getSource(); + dirText.setEnabled(dirCheckBox.getSelection()); + if (!dirText.getEnabled() && dirText.getText().isEmpty()) { + dirText.setText(data.getWorkingDirectory()); + } + } + @Override + public void widgetDefaultSelected(SelectionEvent e) { + // TODO Auto-generated method stub + + } + }); + dirCheckBox.setToolTipText(Activator.getResourceString("easyshell.command.editor.dialog.button.tooltip.useworkdir")); + } + + private void createVariableLabel(Composite parent, String varText, String labelText) { StyledText styledTextWidget = new StyledText(parent, SWT.NONE); styledTextWidget.setText(varText); styledTextWidget.setBackground(parent.getBackground()); @@ -177,6 +215,13 @@ private void refreshCommandTypeCombo() { commandTypeCombo.notifyListeners(SWT.Selection, event); } + private void refreshDirCheckBox() { + // send event to refresh + Event event = new Event(); + event.item = null; + dirCheckBox.notifyListeners(SWT.Selection, event); + } + protected void okPressed() { if (!validateValues()) { return; @@ -184,6 +229,8 @@ protected void okPressed() { data.setResourceType(ResourceType.getFromName(resourceTypeCombo.getText())); data.setCommandType(CommandType.getFromName(commandTypeCombo.getText())); data.setName(nameText.getText()); + data.setUseWorkingDirectory(dirCheckBox.getSelection()); + data.setWorkingDirectory(dirText.getText()); data.setCommand(valueText.getText()); super.okPressed(); } @@ -212,6 +259,14 @@ private boolean validateValues() { valid = false; } + // check working dir + if (valid) { + text = Activator.getResourceString("easyshell.command.editor.dialog.error.text.workingdir"); + if ( (dirText.getText() == null) || (dirText.getText().length() <= 0)) { + valid = false; + } + } + // check value if (valid) { text = Activator.getResourceString("easyshell.command.editor.dialog.error.text.value"); @@ -229,9 +284,8 @@ private boolean validateValues() { private void createResourceTypeCombo(Composite parent) { // draw label - Label comboLabel = new Label(parent,SWT.LEFT); - comboLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END)); - comboLabel.setText(Activator.getResourceString("easyshell.command.editor.dialog.label.combo2")); + createLabel(parent, Activator.getResourceString("easyshell.command.editor.dialog.label.combo2")); + createLabel(parent, ""); // draw combo resourceTypeCombo = new Combo(parent,SWT.BORDER | SWT.READ_ONLY); resourceTypeCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); @@ -259,9 +313,8 @@ public void widgetDefaultSelected(SelectionEvent e) { private void createCommandTypeCombo(Composite parent) { // draw label - Label comboLabel = new Label(parent,SWT.LEFT); - comboLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END)); - comboLabel.setText(Activator.getResourceString("easyshell.command.editor.dialog.label.combo1")); + createLabel(parent, Activator.getResourceString("easyshell.command.editor.dialog.label.combo1")); + createLabel(parent, ""); // draw combo commandTypeCombo = new Combo(parent,SWT.BORDER | SWT.READ_ONLY); commandTypeCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); @@ -287,11 +340,14 @@ public void widgetDefaultSelected(SelectionEvent e) { } } - private Text createTextField(Composite parent, String labelText, String editValue) { + private Text createTextField(Composite parent, String labelText, String editValue, boolean emptyLabel) { // draw label - Label label = new Label(parent,SWT.LEFT); - label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END)); - label.setText(labelText); //$NON-NLS-1$ + if (labelText != null) { + createLabel(parent, labelText); + } + if (emptyLabel) { + createLabel(parent, ""); + } // draw textfield Text text = new Text(parent,SWT.BORDER); text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java index b3a37362..d3a00f1d 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java @@ -24,6 +24,7 @@ import de.anbos.eclipse.easyshell.plugin.Activator; import de.anbos.eclipse.easyshell.plugin.Constants; import de.anbos.eclipse.easyshell.plugin.Utils; +import de.anbos.eclipse.easyshell.plugin.types.Version; public class Initializer extends AbstractPreferenceInitializer { @@ -60,27 +61,29 @@ private void setDefaults(IPreferenceStore store) { private void migrate(IPreferenceStore store) { if (!store.getBoolean(Constants.PREF_MIGRATED)) { int migrateState = -1; // -1 = old store not found, 0 (Yes) = migrated, 1 (No) = no migration wanted by user, 2 (Cancel) = try to migrate again - for (int i=1;i0;i--) { + Version version = Version.values()[i]; + String versionName = version.name(); + if (versionName.startsWith("v1_")) { + migrateState = migrate_from_v1(store, version, migrateState); } else { - migrateState = migrate_from_v2(store, Constants.PREF_VERSIONS[i], migrateState); + migrateState = migrate_from_v2(store, version, migrateState); } // if no old store for this version found continue, else break if (migrateState != -1) { switch(migrateState) { case 0: Utils.showToolTipWarning(null, Activator.getResourceString("easyshell.plugin.name"), MessageFormat.format( Activator.getResourceString("easyshell.message.warning.migrated.yes"), - Constants.PREF_VERSIONS[i])); + versionName)); break; case 1: Utils.showToolTipWarning(null, Activator.getResourceString("easyshell.plugin.name"), MessageFormat.format( Activator.getResourceString("easyshell.message.warning.migrated.no"), - Constants.PREF_VERSIONS[i])); + versionName)); break; case 2: Utils.showToolTipWarning(null, Activator.getResourceString("easyshell.plugin.name"), MessageFormat.format( Activator.getResourceString("easyshell.message.warning.migrated.cancel"), - Constants.PREF_VERSIONS[i])); + versionName)); break; } @@ -98,9 +101,9 @@ private void migrate(IPreferenceStore store) { } } - private int migrate_from_v2(IPreferenceStore store, String version, int migrateState) { + private int migrate_from_v2(IPreferenceStore store, Version version, int migrateState) { // get the old v2 store - IPreferenceStore oldStore = Activator.getDefault().getNewPreferenceStoreByVersion(version); + IPreferenceStore oldStore = Activator.getDefault().getNewPreferenceStoreByVersion(version.name()); // check preferences for default values migrateState = migrate_check_pref_and_ask_user(oldStore, version, Constants.PREF_COMMANDS, migrateState); if (migrateState == 0) { @@ -113,7 +116,7 @@ private int migrate_from_v2(IPreferenceStore store, String version, int migrateS return migrateState; } - private int migrate_check_pref_and_ask_user(IPreferenceStore store, String version, String pref, int migrateState) { + private int migrate_check_pref_and_ask_user(IPreferenceStore store, Version version, String pref, int migrateState) { // if cancel or no just skip this time if (migrateState == 1 || migrateState == 2) { return migrateState; @@ -137,7 +140,7 @@ private int migrate_check_pref_and_ask_user(IPreferenceStore store, String versi return migrateState; } - private int migrate_from_v1(IPreferenceStore store, String version, int migrateState) { + private int migrate_from_v1(IPreferenceStore store, Version version, int migrateState) { // TODO: return -1; } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java index 59effbcf..9854d39e 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java @@ -15,6 +15,7 @@ import java.util.UUID; import de.anbos.eclipse.easyshell.plugin.types.MenuNameType; +import de.anbos.eclipse.easyshell.plugin.types.Version; public class MenuData { @@ -24,8 +25,8 @@ public class MenuData { // menu private boolean enabled = true; - private MenuNameType nameType; - private String namePattern = null; + private MenuNameType nameType = MenuNameType.menuNameTypeUnknown; + private String namePattern = ""; // copy of or reference to command private CommandData commandData = null; @@ -85,7 +86,7 @@ public String getNamePattern() { } public String getNameExpanded() { - return namePattern.replace("${easyshell:command_type}", getCommandData().getCommandType().getName()).replace("${easyshell:command_name}", getCommandData().getName()).replace("${easyshell:command_os}", getCommandData().getOS().getName()); + return namePattern.replace("${easyshell:command_type}", getCommandData().getCommandType().getName()).replace("${easyshell:command_name}", getCommandData().getName()).replace("${easyshell:command_os}", getCommandData().getOs().getName()); } public CommandData getCommandData() { @@ -108,27 +109,7 @@ public boolean equals(Object object) { return false; } - public boolean deserialize(String value, StringTokenizer tokenizer, String delimiter) { - if((value == null || value.length() <= 0) && tokenizer == null) { - return false; - } - if (tokenizer == null) { - tokenizer = new StringTokenizer(value,delimiter); - } - // set internal members - setPosition(Integer.parseInt(tokenizer.nextToken())); - setId(tokenizer.nextToken()); - // set menu data members - setEnabled(Boolean.valueOf(tokenizer.nextToken()).booleanValue()); - setNameType(MenuNameType.getFromEnum(tokenizer.nextToken())); - setNamePattern(tokenizer.nextToken()); - // set command data members - setCommandData(new CommandData()); - getCommandData().deserialize(null, tokenizer, delimiter); - return true; - } - - public boolean deserialize_v2_0_001(String value, StringTokenizer tokenizer, String delimiter) { + public boolean deserialize(Version version, String value, StringTokenizer tokenizer, String delimiter) { if((value == null || value.length() <= 0) && tokenizer == null) { return false; } @@ -140,35 +121,56 @@ public boolean deserialize_v2_0_001(String value, StringTokenizer tokenizer, Str setId(tokenizer.nextToken()); // set menu data members setEnabled(Boolean.valueOf(tokenizer.nextToken()).booleanValue()); - // ------------------------------------------------- - // convert handling + // menu name type handling MenuNameType nameType = MenuNameType.menuNameTypeUser; + if (version.getId() >= Version.v2_0_002.getId()) { + nameType = MenuNameType.getFromEnum(tokenizer.nextToken()); + } String namePatternReaded = tokenizer.nextToken(); // ------------------------------------------------- // set command data members setCommandData(new CommandData()); - getCommandData().deserialize(null, tokenizer, delimiter); - // ------------------------------------------------- - // convert handling - // check if readed name is the same, like expanded from patterns - for (MenuNameType type : MenuNameType.getAsList()) { - setNamePattern(type.getPattern()); // set temporary - if (getNameExpanded().equals(namePatternReaded)) { - nameType = type; - break; + getCommandData().deserialize(version, null, tokenizer, delimiter); + // menu name type handling + if (version.getId() < Version.v2_0_002.getId()) { + // check if readed name is the same, like expanded from patterns + for (MenuNameType type : MenuNameType.getAsList()) { + setNamePattern(type.getPattern()); // set temporary + if (getNameExpanded().equals(namePatternReaded)) { + nameType = type; + break; + } } - } - setNameType(nameType); - // if not found set the readed value - if (nameType == MenuNameType.menuNameTypeUser) { + setNameType(nameType); + // if not found set the readed value + if (nameType == MenuNameType.menuNameTypeUser) { + setNamePattern(namePatternReaded); + } + } else { + setNameType(nameType); setNamePattern(namePatternReaded); } - // ------------------------------------------------- return true; } + public boolean deserialize(String value, StringTokenizer tokenizer, String delimiter) { + return deserialize(Version.actual, value, tokenizer, delimiter); + } + + public String serialize(Version version, String delimiter) { + String ret = Integer.toString(getPosition()) + delimiter; + ret += getId() + delimiter; + ret += Boolean.toString(isEnabled()) + delimiter; + if (version.getId() >= Version.v2_0_002.getId()) { + ret += getNameType().toString() + delimiter; + } + ret += getNamePattern() + delimiter; + ret += commandData.serialize(version, delimiter); + return ret; + } + public String serialize(String delimiter) { - return Integer.toString(getPosition()) + delimiter + getId() + delimiter + Boolean.toString(isEnabled()) + delimiter + getNameType().toString() + delimiter + getNamePattern() + delimiter + commandData.serialize(delimiter); + return serialize(Version.actual, delimiter); } public void setPosition(int position) { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java index bfd6869b..4553541a 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java @@ -356,7 +356,7 @@ private void createEnabledCheckBox(Composite parent) { } private String getCommandAsComboName(CommandData data) { - return data.getPresetType().getName() + " - " + data.getOS().getName() + " - " + data.getCommandType().getName() + " - " + data.getName(); + return data.getPresetType().getName() + " - " + data.getOs().getName() + " - " + data.getCommandType().getName() + " - " + data.getName(); } private String[] getAllCommandsAsComboNames(List list) { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataLabelProvider.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataLabelProvider.java index adb0f32c..06b8480b 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataLabelProvider.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataLabelProvider.java @@ -26,7 +26,7 @@ public Image getColumnImage(Object element, int columnIndex) { MenuData data = (MenuData)element; switch(columnIndex) { case 0: - return new Image(null, Activator.getImageDescriptor(data.getCommandData().getTypeIcon()).getImageData()); + return new Image(null, Activator.getImageDescriptor(data.getCommandData().getCommandType().getIcon()).getImageData()); default: return null; } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceValueConverter.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceValueConverter.java index 0a754048..6ea265a4 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceValueConverter.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/PreferenceValueConverter.java @@ -15,6 +15,7 @@ import java.util.StringTokenizer; import de.anbos.eclipse.easyshell.plugin.types.PresetType; +import de.anbos.eclipse.easyshell.plugin.types.Version; public class PreferenceValueConverter { @@ -81,10 +82,11 @@ public static MenuData asMenuData(String value) { return data; } - public static CommandData migrateCommandData(String version, String value) { + public static CommandData migrateCommandData(Version version, String value) { CommandData data = new CommandData(); - if (version.equals("v2_0_001")) { - data.deserialize_v2_0_001(value, null, VALUE_DELIMITER); + data.deserialize(version, value, null, VALUE_DELIMITER); + // special handling + if (version == Version.v2_0_001) { // skip commands from preset if (data.getPresetType() == PresetType.presetPlugin) { data = null; @@ -93,15 +95,13 @@ public static CommandData migrateCommandData(String version, String value) { return data; } - public static MenuData migrateMenuData(String version, String value) { + public static MenuData migrateMenuData(Version version, String value) { MenuData data = new MenuData(); - if (version.equals("v2_0_001")) { - data.deserialize_v2_0_001(value, null, VALUE_DELIMITER); - } + data.deserialize(version, value, null, VALUE_DELIMITER); return data; } - public static String migrateCommandDataList(String version, String value) { + public static String migrateCommandDataList(Version version, String value) { StringBuffer buffer = new StringBuffer(); StringTokenizer tokenizer = new StringTokenizer(value, ITEM_DELIMITER); int num = tokenizer.countTokens(); @@ -115,7 +115,7 @@ public static String migrateCommandDataList(String version, String value) { return buffer.toString(); } - public static String migrateMenuDataList(String version, String value) { + public static String migrateMenuDataList(Version version, String value) { StringBuffer buffer = new StringBuffer(); StringTokenizer tokenizer = new StringTokenizer(value, ITEM_DELIMITER); int num = tokenizer.countTokens(); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/CommandType.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/CommandType.java index 1a69e784..7fd53fc7 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/CommandType.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/CommandType.java @@ -68,14 +68,7 @@ public static CommandType getFromName(String name) { return ret; } public static CommandType getFromEnum(String name) { - CommandType ret = commandTypeUnknown; - for(int i = 0; i < CommandType.values().length; i++) { - if (CommandType.values()[i].toString().equals(name)) { - ret = CommandType.values()[i]; - break; - } - } - return ret; + return CommandType.valueOf(name); } public static CommandType getFromAction(String action) { CommandType ret = commandTypeUnknown; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Debug.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Debug.java index de387ad3..2ad7f53a 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Debug.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Debug.java @@ -53,13 +53,6 @@ public static Debug getFromName(String name) { return ret; } public static Debug getFromEnum(String name) { - Debug ret = debugUnknown; - for(int i = 0; i < Debug.values().length; i++) { - if (Debug.values()[i].toString().equals(name)) { - ret = Debug.values()[i]; - break; - } - } - return ret; + return Debug.valueOf(name); } } \ No newline at end of file diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/LinuxDesktop.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/LinuxDesktop.java index acbce651..d0ffcdad 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/LinuxDesktop.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/LinuxDesktop.java @@ -55,13 +55,6 @@ public static LinuxDesktop getFromName(String name) { return ret; } public static LinuxDesktop getFromEnum(String name) { - LinuxDesktop ret = desktopUnknown; - for(int i = 0; i < LinuxDesktop.values().length; i++) { - if (LinuxDesktop.values()[i].toString().equals(name)) { - ret = LinuxDesktop.values()[i]; - break; - } - } - return ret; + return LinuxDesktop.valueOf(name); } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/MenuNameType.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/MenuNameType.java index d1b589e5..e12da40a 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/MenuNameType.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/MenuNameType.java @@ -60,14 +60,7 @@ public static MenuNameType getFromName(String name) { return ret; } public static MenuNameType getFromEnum(String name) { - MenuNameType ret = menuNameTypeUnknown; - for(int i = 0; i < MenuNameType.values().length; i++) { - if (MenuNameType.values()[i].toString().equals(name)) { - ret = MenuNameType.values()[i]; - break; - } - } - return ret; + return MenuNameType.valueOf(name); } public static MenuNameType getFromPattern(String pattern) { MenuNameType ret = menuNameTypeUnknown; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/OS.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/OS.java index 1bfc32c6..1a206438 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/OS.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/OS.java @@ -54,14 +54,7 @@ public static OS getFromName(String name) { return ret; } public static OS getFromEnum(String name) { - OS ret = osUnknown; - for(int i = 0; i < OS.values().length; i++) { - if (OS.values()[i].toString().equals(name)) { - ret = OS.values()[i]; - break; - } - } - return ret; + return OS.valueOf(name); } public static List getNamesAsList() { List list = new ArrayList(); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/PresetType.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/PresetType.java index d8bc0f18..64a4465a 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/PresetType.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/PresetType.java @@ -53,14 +53,7 @@ public static PresetType getFromName(String name) { return ret; } public static PresetType getFromEnum(String name) { - PresetType ret = presetUnknown; - for(int i = 0; i < PresetType.values().length; i++) { - if (PresetType.values()[i].toString().equals(name)) { - ret = PresetType.values()[i]; - break; - } - } - return ret; + return PresetType.valueOf(name); } public static List getNamesAsList() { List list = new ArrayList(); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Quotes.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Quotes.java index 4a1fec67..640d1b23 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Quotes.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Quotes.java @@ -57,13 +57,6 @@ public static Quotes getFromName(String name) { return ret; } public static Quotes getFromEnum(String name) { - Quotes ret = quotesUnknown; - for(int i = 0; i < Quotes.values().length; i++) { - if (Quotes.values()[i].toString().equals(name)) { - ret = Quotes.values()[i]; - break; - } - } - return ret; + return Quotes.valueOf(name); } } \ No newline at end of file diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/ResourceType.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/ResourceType.java index 538e1580..c9897435 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/ResourceType.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/ResourceType.java @@ -54,14 +54,7 @@ public static ResourceType getFromName(String name) { return ret; } public static ResourceType getFromEnum(String name) { - ResourceType ret = resourceTypeUnknown; - for(int i = 0; i < ResourceType.values().length; i++) { - if (ResourceType.values()[i].toString().equals(name)) { - ret = ResourceType.values()[i]; - break; - } - } - return ret; + return ResourceType.valueOf(name); } public static List getNamesAsList() { List list = new ArrayList(); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Tokenizer.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Tokenizer.java index cf4ea3a0..66fe5b03 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Tokenizer.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Tokenizer.java @@ -50,13 +50,6 @@ public static Tokenizer getFromName(String name) { return ret; } public static Tokenizer getFromEnum(String name) { - Tokenizer ret = tokenizerUnknown; - for(int i = 0; i < Tokenizer.values().length; i++) { - if (Tokenizer.values()[i].toString().equals(name)) { - ret = Tokenizer.values()[i]; - break; - } - } - return ret; + return Tokenizer.valueOf(name); } }; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Version.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Version.java new file mode 100644 index 00000000..fb66fcad --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Version.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.types; + +import java.util.ArrayList; +import java.util.List; + +public enum Version { + vUnknown(-1, "Unknown"), + v1_4(0, "v1.4.x"), + v2_0_001(1, "v2.0.x"), + v2_0_002(2, "v2.0.x"), + v2_0_003(3, "v2.0.x"); + public static Version actual = v2_0_003; + // attributes + private final int id; + private final String name; + // construct + Version(int id, String name) { + this.id = id; + this.name = name; + } + public int getId() { + return id; + } + public String getName() { + return name; + } + public static Version getFromId(int id) { + Version ret = vUnknown; + for(int i = 0; i < Version.values().length; i++) { + if (Version.values()[i].getId() == id) { + ret = Version.values()[i]; + break; + } + } + return ret; + } + public static Version getFromName(String name) { + Version ret = vUnknown; + for(int i = 0; i < Version.values().length; i++) { + if (Version.values()[i].getName().equals(name)) { + ret = Version.values()[i]; + break; + } + } + return ret; + } + public static Version getFromEnum(String name) { + return Version.valueOf(name); + } + public static List getNamesAsList() { + List list = new ArrayList(); + for(int i = 0; i < Version.values().length; i++) { + list.add(Version.values()[i].getName()); + } + return list; + } +} From e5684e84147008488ad79a90c41203a2208b1ad4 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Fri, 22 Jul 2016 00:08:41 +0200 Subject: [PATCH 19/73] changed version names for dialogs and tooltips Signed-off-by: Andre Bossert --- .../eclipse/easyshell/plugin/preferences/Initializer.java | 6 +++--- .../de/anbos/eclipse/easyshell/plugin/types/Version.java | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java index d3a00f1d..3c4c4ab4 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java @@ -63,8 +63,8 @@ private void migrate(IPreferenceStore store) { int migrateState = -1; // -1 = old store not found, 0 (Yes) = migrated, 1 (No) = no migration wanted by user, 2 (Cancel) = try to migrate again for (int i=Version.values().length-2;i>0;i--) { Version version = Version.values()[i]; - String versionName = version.name(); - if (versionName.startsWith("v1_")) { + String versionName = version.getName(); + if (version.toString().startsWith("v1_")) { migrateState = migrate_from_v1(store, version, migrateState); } else { migrateState = migrate_from_v2(store, version, migrateState); @@ -128,7 +128,7 @@ private int migrate_check_pref_and_ask_user(IPreferenceStore store, Version vers String title = Activator.getResourceString("easyshell.plugin.name"); String question = MessageFormat.format( Activator.getResourceString("easyshell.question.migrate"), - version); + version.getName()); MessageDialog dialog = new MessageDialog( null, title, null, question, MessageDialog.QUESTION, diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Version.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Version.java index fb66fcad..104e425c 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Version.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Version.java @@ -17,9 +17,9 @@ public enum Version { vUnknown(-1, "Unknown"), v1_4(0, "v1.4.x"), - v2_0_001(1, "v2.0.x"), - v2_0_002(2, "v2.0.x"), - v2_0_003(3, "v2.0.x"); + v2_0_001(1, "v2.0 beta 1"), + v2_0_002(2, "v2.0 beta 2"), + v2_0_003(3, "v2.0 beta 3"); public static Version actual = v2_0_003; // attributes private final int id; From 455788d489b7a0eb87fb8d1764787e8a7cca0fa9 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Fri, 22 Jul 2016 14:25:35 +0200 Subject: [PATCH 20/73] major refactoring of preferences (data and view) fixed: - #59 [v2.0] columns in prefence table are not draggable/movable new or refactored: - refactored table viewer creation - refactored data and interfaces - added preset/commands page - added command page - added search fields Signed-off-by: Andre Bossert --- plugin/plugin.xml | 21 +- .../easyshell/plugin/UIMessages.properties | 62 ++- .../plugin/preferences/CommandData.java | 28 +- .../CommandDataContentProvider.java | 29 ++ .../preferences/CommandDataLabelProvider.java | 50 +++ .../plugin/preferences/CommandDataStore.java | 145 +----- .../plugin/preferences/CommandPage.java | 416 ++++++++++++++++++ .../preferences/CommandTableFilter.java | 41 ++ .../easyshell/plugin/preferences/Data.java | 94 ++++ .../plugin/preferences/DataMover.java | 54 +++ .../plugin/preferences/DataStore.java | 201 +++++++++ .../easyshell/plugin/preferences/IData.java | 15 + .../plugin/preferences/IDataStore.java | 23 + .../plugin/preferences/MainPage.java | 49 +++ .../plugin/preferences/MenuData.java | 30 +- .../plugin/preferences/MenuDataMover.java | 49 +-- .../plugin/preferences/MenuDataStore.java | 137 +----- .../{CommandsPage.java => MenuPage.java} | 373 +++++++--------- .../plugin/preferences/MenuTableFilter.java | 44 ++ .../easyshell/plugin/types/Version.java | 4 +- 20 files changed, 1284 insertions(+), 581 deletions(-) create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataContentProvider.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataLabelProvider.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandTableFilter.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Data.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/DataMover.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/DataStore.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/IData.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/IDataStore.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MainPage.java rename plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/{CommandsPage.java => MenuPage.java} (64%) create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuTableFilter.java diff --git a/plugin/plugin.xml b/plugin/plugin.xml index 776e287a..3e45ff0b 100644 --- a/plugin/plugin.xml +++ b/plugin/plugin.xml @@ -22,6 +22,11 @@ name="value" optional="false"> + + + + + + diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties index ba536484..9f31a469 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties @@ -14,26 +14,47 @@ easyshell.message.warning.migrated.cancel=Migration was canceled and will be exe easyshell.message.warning.migrated.default=First startup!\n\nPlease verify applied default settings! easyshell.question.migrate=Do you want to migrate your settings from previous version "{0}" ? -easyshell.page.table.header.title.column0=Name -easyshell.page.table.header.title.column1=Command -easyshell.page.table.button.text.new=Add... -easyshell.page.table.button.tooltip.new=Add new menu -easyshell.page.table.button.text.copy=Copy... -easyshell.page.table.button.tooltip.copy=Copy selected menu as new menu -easyshell.page.table.button.text.edit=Edit... -easyshell.page.table.button.tooltip.edit=Edit selected menu -easyshell.page.table.button.text.remove=Remove... -easyshell.page.table.button.tooltip.remove=Remove selected menu(s) -easyshell.page.table.button.text.up=Up -easyshell.page.table.button.tooltip.up=Move selected menu up -easyshell.page.table.button.text.down=Down -easyshell.page.table.button.tooltip.down=Move selected menu down -easyshell.page.table.dialog.remove.title=Remove menu(s) -easyshell.page.table.dialog.remove.question=Do you really want to remove selected menu(s) ? -easyshell.page.table.dialog.defaults.title=Restore defaults -easyshell.page.table.dialog.defaults.question=All your menu definitions will be overwritten!\n\nYou can still use "Cancel" button afterwards for undo.\n\nDo you really want to restore default settings? -easyshell.page.table.dialog.migration.title=Migration -easyshell.page.table.dialog.migration.question=You have canceled the migration of settings from previous version.\n\nAll your menu definitions will be written now and migration will be skipped completely!\n\nDo you really want to overwrite the migrated settings? +easyshell.menu.page.header.title.column0=Menu +easyshell.menu.page.header.title.column1=Command +easyshell.menu.page.button.text.new=Add... +easyshell.menu.page.button.tooltip.new=Add new menu +easyshell.menu.page.button.text.copy=Copy... +easyshell.menu.page.button.tooltip.copy=Copy selected menu as new menu +easyshell.menu.page.button.text.edit=Edit... +easyshell.menu.page.button.tooltip.edit=Edit selected menu +easyshell.menu.page.button.text.remove=Remove... +easyshell.menu.page.button.tooltip.remove=Remove selected menu(s) +easyshell.menu.page.button.text.up=Up +easyshell.menu.page.button.tooltip.up=Move selected menu up +easyshell.menu.page.button.text.down=Down +easyshell.menu.page.button.tooltip.down=Move selected menu down +easyshell.menu.page.dialog.remove.title=Remove menu(s) +easyshell.menu.page.dialog.remove.question=Do you really want to remove selected menu(s) ? + +easyshell.menu.page.dialog.defaults.title=Restore defaults +easyshell.menu.page.dialog.defaults.question=All your menu definitions will be overwritten!\n\nYou can still use "Cancel" button afterwards for undo.\n\nDo you really want to restore default settings? +easyshell.menu.page.dialog.migration.title=Migration +easyshell.menu.page.dialog.migration.question=You have canceled the migration of settings from previous version.\n\nAll your menu definitions will be written now and migration will be skipped completely!\n\nDo you really want to overwrite the migrated settings? + +easyshell.command.page.header.title.column0=Name +easyshell.command.page.header.title.column1=Command +easyshell.command.page.text.text.search=Search +easyshell.command.page.text.tooltip.search=Enter your search pattern here +easyshell.command.page.button.text.new=Add... +easyshell.command.page.button.tooltip.new=Add new menu +easyshell.command.page.button.text.copy=Copy... +easyshell.command.page.button.tooltip.copy=Copy selected menu as new menu +easyshell.command.page.button.text.edit=Edit... +easyshell.command.page.button.tooltip.edit=Edit selected menu +easyshell.command.page.button.text.remove=Remove... +easyshell.command.page.button.tooltip.remove=Remove selected commands(s) +easyshell.command.page.dialog.remove.title=Remove command(s) +easyshell.command.page.dialog.remove.question=Do you really want to remove selected command(s) ? + +easyshell.command.page.dialog.defaults.title=Restore defaults +easyshell.command.page.dialog.defaults.question=All your command definitions will be overwritten!\n\nYou can still use "Cancel" button afterwards for undo.\n\nDo you really want to restore default settings? +easyshell.command.page.dialog.migration.title=Migration +easyshell.command.page.dialog.migration.question=You have canceled the migration of settings from previous version.\n\nAll your command definitions will be written now and migration will be skipped completely!\n\nDo you really want to overwrite the migrated settings? easyshell.menu.editor.dialog.title.new=Create new menu easyshell.menu.editor.dialog.title.edit=Edit existing menu @@ -47,6 +68,7 @@ easyshell.menu.editor.dialog.label.pattern= easyshell.menu.editor.dialog.label.combo.preset=select: easyshell.menu.editor.dialog.label.combo.pattern=name pattern: easyshell.menu.editor.dialog.label.command=command: + easyshell.menu.editor.dialog.button.text.new=New... easyshell.menu.editor.dialog.button.tooltip.new=Add new user command easyshell.menu.editor.dialog.button.text.copy=Copy... diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java index 3c79e3ab..a59a1849 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java @@ -20,11 +20,7 @@ import de.anbos.eclipse.easyshell.plugin.types.ResourceType; import de.anbos.eclipse.easyshell.plugin.types.Version; -public class CommandData { - - // internal - private int position = 0; - private String id = null; +public class CommandData extends Data { // command private PresetType presetType = PresetType.presetUnknown; @@ -37,11 +33,7 @@ public class CommandData { private String command = ""; public CommandData(String id, PresetType presetType, OS os, String name, ResourceType resType, boolean useWorkingDirectory, String workingDirectory, CommandType cmdType, String command) { - if (id == null || id.isEmpty()) { - this.id = UUID.randomUUID().toString(); - } else { - this.id = id; - } + super(id); this.presetType = presetType; this.os = os; this.name = name; @@ -67,14 +59,6 @@ public CommandData(CommandData commandData, boolean generateNewId) { public CommandData() { } - public int getPosition() { - return position; - } - - public String getId() { - return id; - } - public String getName() { return name; } @@ -107,14 +91,6 @@ public String getCommand() { return command; } - public void setPosition(int position) { - this.position = position; - } - - public void setId(String id) { - this.id = id; - } - public void setName(String name) { this.name = name; } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataContentProvider.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataContentProvider.java new file mode 100644 index 00000000..ef16a8bf --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataContentProvider.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.Viewer; + +public class CommandDataContentProvider implements IStructuredContentProvider { + + public Object[] getElements(Object inputElement) { + return ((CommandDataStore)inputElement).getAllCommandsArray(); + } + + public void dispose() { + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataLabelProvider.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataLabelProvider.java new file mode 100644 index 00000000..19eb2ad2 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataLabelProvider.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.swt.graphics.Image; + +import de.anbos.eclipse.easyshell.plugin.Activator; + +public class CommandDataLabelProvider extends LabelProvider implements ITableLabelProvider { + + public Image getColumnImage(Object element, int columnIndex) { + if(!(element instanceof CommandData)) { + return null; + } + CommandData data = (CommandData)element; + switch(columnIndex) { + case 0: + return new Image(null, Activator.getImageDescriptor(data.getCommandType().getIcon()).getImageData()); + default: + return null; + } + } + + public String getColumnText(Object element, int columnIndex) { + if(!(element instanceof CommandData)) { + return ""; + } + CommandData data = (CommandData)element; + switch(columnIndex) { + case 0: + return data.getName(); + case 1: + return data.getCommand(); + default: + return ""; + } + } + +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataStore.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataStore.java index 703caa46..34975c90 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataStore.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataStore.java @@ -12,8 +12,6 @@ package de.anbos.eclipse.easyshell.plugin.preferences; import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; import java.util.List; import org.eclipse.jface.preference.IPreferenceStore; @@ -21,24 +19,15 @@ import de.anbos.eclipse.easyshell.plugin.Constants; import de.anbos.eclipse.easyshell.plugin.types.PresetType; -public class CommandDataStore { - - private IPreferenceStore store; - private List items; - private DataObjectComparator comparator; +public class CommandDataStore extends DataStore { public CommandDataStore(IPreferenceStore store) { - items = new ArrayList(); - this.store = store; - } - - public List getAllCommands() { - return items; + super(store); } private List getUserCommands() { List userItems = new ArrayList(); - for (CommandData data : items) { + for (CommandData data : getDataList()) { if (data.getPresetType() == PresetType.presetUser) { userItems.add(data); } @@ -48,7 +37,7 @@ private List getUserCommands() { private List getPresetCommands() { List presetItems = new ArrayList(); - for (CommandData data : items) { + for (CommandData data : getDataList()) { if (data.getPresetType() == PresetType.presetPlugin) { presetItems.add(data); } @@ -57,7 +46,7 @@ private List getPresetCommands() { } public CommandData[] getAllCommandsArray() { - List allItems = getAllCommands(); + List allItems = getDataList(); if(allItems.size() <= 0) { return new CommandData[0]; } @@ -68,96 +57,32 @@ public CommandData[] getAllCommandsArray() { return allArray; } - public CommandData getPreviousElement(CommandData data) { - sort(); - for(int i = 0 ; i < items.size() ; i++) { - CommandData item = (CommandData)items.get(i); - if(item.equals(data)) { - try { - return (CommandData)items.get(i - 1); - } catch(Throwable t) { - return null; - } - } - } - return null; - } - - public CommandData getNextElement(CommandData data) { - sort(); - for(int i = 0 ; i < items.size() ; i++) { - CommandData item = (CommandData)items.get(i); - if(item.equals(data)) { - try { - return (CommandData)items.get(i + 1); - } catch(Throwable t) { - return null; - } - } - } - return null; - } - - public CommandData getLastElement() { - sort(); - int index = items.size() - 1; - if(index < 0) { - return null; - } - return (CommandData)items.get(index); - } - - public void add(CommandData data) { - int position = 0; - CommandData lastElement = getLastElement(); - if(lastElement != null) { - position = lastElement.getPosition() + 1; - } - data.setPosition(position); - items.add(data); - sort(); - } - - public void replace(CommandData data) { - items.set(data.getPosition(), data); - //sort(); - } - - public void delete(CommandData data) { - items.remove(data); - sort(); - } - public void save() { - store.setValue(Constants.PREF_COMMANDS_PRESET,PreferenceValueConverter.asCommandDataString(getPresetCommands())); - store.setValue(Constants.PREF_COMMANDS,PreferenceValueConverter.asCommandDataString(getUserCommands())); + getStore().setValue(Constants.PREF_COMMANDS_PRESET,PreferenceValueConverter.asCommandDataString(getPresetCommands())); + getStore().setValue(Constants.PREF_COMMANDS,PreferenceValueConverter.asCommandDataString(getUserCommands())); } public void loadDefaults() { - store.setToDefault(Constants.PREF_COMMANDS_PRESET); - store.setToDefault(Constants.PREF_COMMANDS); + getStore().setToDefault(Constants.PREF_COMMANDS_PRESET); + getStore().setToDefault(Constants.PREF_COMMANDS); load(); } public void load() { - CommandData[] arrayPreset = PreferenceValueConverter.asCommandDataArray(store.getString(Constants.PREF_COMMANDS_PRESET)); - CommandData[] arrayUser = PreferenceValueConverter.asCommandDataArray(store.getString(Constants.PREF_COMMANDS)); - this.items.clear(); + CommandData[] arrayPreset = PreferenceValueConverter.asCommandDataArray(getStore().getString(Constants.PREF_COMMANDS_PRESET)); + CommandData[] arrayUser = PreferenceValueConverter.asCommandDataArray(getStore().getString(Constants.PREF_COMMANDS)); + removeAll(); for(int i = 0 ; i < arrayPreset.length ; i++) { - this.items.add(arrayPreset[i]); + addItem(arrayPreset[i]); } for(int i = 0 ; i < arrayUser.length ; i++) { - this.items.add(arrayUser[i]); + addItem(arrayUser[i]); } sort(); } - public void removeAll() { - items.clear(); - } - public CommandData getCommandDataByName(String name) { - for (CommandData data : items) { + for (CommandData data : getDataList()) { if (data.getName().equals(name)) { return data; } @@ -165,44 +90,4 @@ public CommandData getCommandDataByName(String name) { return null; } - public CommandData getCommandDataByPosition(int position) { - return items.get(position); - } - - private void sort() { - if(comparator == null) { - comparator = new DataObjectComparator(); - } - Collections.sort(items, comparator); - for (int i=0;i { - public int compare(Object object1, Object object2) { - CommandData data1 = null; - CommandData data2 = null; - if(object1 instanceof CommandData) { - data1 = (CommandData)object1; - } - if(object2 instanceof CommandData) { - data2 = (CommandData)object2; - } - if(data1 == null || data2 == null) { - return -1; - } - if(data1.getPosition() > data2.getPosition()) { - return 1; - } - if(data1.getPosition() == data2.getPosition()) { - return 0; - } - if(data1.getPosition() < data2.getPosition()) { - return -1; - } - return -1; - } - } - } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java new file mode 100644 index 00000000..4ee356d6 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java @@ -0,0 +1,416 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +import java.util.Iterator; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerSorter; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; + +import de.anbos.eclipse.easyshell.plugin.Activator; +import de.anbos.eclipse.easyshell.plugin.Utils; +import de.anbos.eclipse.easyshell.plugin.types.CommandType; +import de.anbos.eclipse.easyshell.plugin.types.PresetType; +import de.anbos.eclipse.easyshell.plugin.types.ResourceType; + +public class CommandPage extends org.eclipse.jface.preference.PreferencePage + implements IWorkbenchPreferencePage { + + private CommandDataStore commandStore; + private Text searchText; + private CommandTableFilter filter; + private TableViewer tableViewer; + private Button addNewButton; + private Button addCopyButton; + private Button editButton; + private Button removeButton; + + @Override + public void init(IWorkbench workbench) { + } + + @Override + public boolean performOk() { + boolean save = true; + if (!commandStore.isMigrated()) { + String title = Activator.getResourceString("easyshell.command.page.dialog.migration.title"); + String question = Activator.getResourceString("easyshell.command.page.dialog.migration.question"); + MessageDialog dialog = new MessageDialog( + null, title, null, question, + MessageDialog.WARNING, + new String[] {"Yes", "No"}, + 1); // no is the default + int result = dialog.open(); + if (result == 0) { + commandStore.setMigrated(true); + } else { + save = false; + } + } + if (save) { + commandStore.save(); + } + return save; + } + + @Override + protected void performDefaults() { + String title = Activator.getResourceString("easyshell.command.page.dialog.defaults.title"); + String question = Activator.getResourceString("easyshell.command.page.dialog.defaults.question"); + MessageDialog dialog = new MessageDialog( + null, title, null, question, + MessageDialog.WARNING, + new String[] {"Yes", "No"}, + 1); // no is the default + int result = dialog.open(); + if (result == 0) { + commandStore.loadDefaults(); + tableViewer.refresh(); + } + } + + @Override + protected void performApply() { + performOk(); + } + + @Override + protected Control createContents(Composite parent) { + // main page composite + Composite pageComponent = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(3, false); + pageComponent.setLayout(layout); + //parent.setLayout(layout); + + // search + createSearchField(pageComponent); + + // command store + commandStore = new CommandDataStore(Activator.getDefault().getPreferenceStore()); + commandStore.load(); + + // table viewer + createTableViewer(pageComponent); + + // buttons + createButtons(pageComponent); + + // send event to refresh tableViewer + Event event = new Event(); + event.item = null; + tableViewer.refresh(); + tableViewer.getTable().notifyListeners(SWT.Selection, event); + + return pageComponent; + } + + private void createSearchField(Composite parent) { + /* + Group group = new Group(parent, SWT.SHADOW_ETCHED_IN); + group.setText(Activator.getResourceString("easyshell.command.page.text.text.search")); + group.setToolTipText(Activator.getResourceString("easyshell.command.page.text.tooltip.search")); + GridLayout layout2 = new GridLayout(); + layout2.numColumns = 1; + layout2.makeColumnsEqualWidth = false; + layout2.marginWidth = 5; + layout2.marginHeight = 4; + group.setLayout(layout2); + GridData data2 = new GridData(GridData.FILL_HORIZONTAL); + group.setLayoutData(data2); + group.setFont(parent.getFont());*/ + + //Label searchLabel = new Label(parent, SWT.NONE); + //searchLabel.setText("Search: "); + filter = new CommandTableFilter(); + searchText = new Text(parent, SWT.BORDER | SWT.SEARCH); + searchText.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL + | GridData.HORIZONTAL_ALIGN_FILL)); + searchText.addKeyListener(new KeyAdapter() { + public void keyReleased(KeyEvent ke) { + filter.setSearchText(searchText.getText()); + tableViewer.refresh(); + } + + }); + searchText.setToolTipText(Activator.getResourceString("easyshell.command.page.text.tooltip.search")); + // fake + Label label = new Label(parent, SWT.NONE); + label.setText(""); + } + + private void createButtons(Composite pageComponent) { + Font font = pageComponent.getFont(); + // button pageComponent + Composite groupComponent = new Composite(pageComponent, SWT.NULL); + GridLayout groupLayout = new GridLayout(); + groupLayout.marginWidth = 0; + groupLayout.marginHeight = 0; + groupComponent.setLayout(groupLayout); + GridData gridData = new GridData(); + gridData.verticalAlignment = GridData.FILL; + gridData.horizontalAlignment = GridData.FILL; + groupComponent.setLayoutData(gridData); + groupComponent.setFont(font); + + // buttons + createNewButton(font, gridData, groupComponent); + createCopyButton(font, gridData, groupComponent); + createEditButton(font, gridData, groupComponent); + createRemoveButton(font, gridData, groupComponent); + } + + private void createTableViewer(Composite parent) { + tableViewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL + | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER); + createColumns(parent, tableViewer); + final Table table = tableViewer.getTable(); + table.setHeaderVisible(true); + table.setLinesVisible(true); + + tableViewer.setLabelProvider(new CommandDataLabelProvider()); + tableViewer.setContentProvider(new CommandDataContentProvider()); + tableViewer.addFilter(filter); + + // Get the content for the viewer, setInput will call getElements in the + // contentProvider + tableViewer.setInput(commandStore); + + // Layout the viewer + GridData gridData = new GridData(); + gridData.verticalAlignment = GridData.FILL; + gridData.horizontalSpan = 2; + gridData.grabExcessHorizontalSpace = true; + gridData.grabExcessVerticalSpace = true; + gridData.horizontalAlignment = GridData.FILL; + tableViewer.getControl().setLayoutData(gridData); + + tableViewer.addDoubleClickListener(new IDoubleClickListener() { + @Override + public void doubleClick(DoubleClickEvent event) { + editDialog(); + } + }); + + tableViewer.addSelectionChangedListener(new ISelectionChangedListener() { + @Override + public void selectionChanged(SelectionChangedEvent event) { + IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection(); + boolean selected = !selection.isEmpty(); + boolean presetSelected = false; + Iterator elements = selection.iterator(); + while (elements.hasNext()) { + CommandData data = (CommandData) elements.next(); + if (data.getPresetType() == PresetType.presetPlugin) { + presetSelected = true; + break; + } + } + addCopyButton.setEnabled(selected); + editButton.setEnabled(selected && !presetSelected); + removeButton.setEnabled(selected && !presetSelected); + } + }); + + tableViewer.setSorter(new ViewerSorter() { + public int compare(Viewer viewer, Object object1, Object object2) { + if (!(object1 instanceof CommandData) || !(object2 instanceof CommandData)) { + return super.compare(viewer, object1, object2); + } + CommandData data1 = (CommandData) object1; + CommandData data2 = (CommandData) object2; + if (data1.getPosition() > data2.getPosition()) { + return 1; + } + if (data1.getPosition() < data2.getPosition()) { + return -1; + } + if (data1.getPosition() == data2.getPosition()) { + return 0; + } + return super.compare(viewer, object1, object2); + } + public boolean isSorterProperty(Object element, String property) { + return true; + } + }); + } + + private void createColumns(final Composite parent, final TableViewer viewer) { + TableViewerColumn viewerColumn1 = new TableViewerColumn(viewer, + SWT.NONE); + TableColumn column1 = viewerColumn1.getColumn(); + column1.setText(Activator.getResourceString("easyshell.command.page.header.title.column0")); + column1.setWidth(200); + column1.setResizable(true); + column1.setMoveable(true); + + TableViewerColumn viewerColumn2 = new TableViewerColumn(viewer, + SWT.NONE); + TableColumn column2 = viewerColumn2.getColumn(); + column2.setText(Activator.getResourceString("easyshell.command.page.header.title.column1")); + column2.setWidth(400); + column2.setResizable(true); + column2.setMoveable(true); + } + + private void createRemoveButton(Font font, GridData gridData, Composite groupComponent) { + removeButton = new Button(groupComponent, SWT.PUSH); + removeButton.setText(Activator.getResourceString("easyshell.command.page.button.text.remove")); + removeButton.setToolTipText(Activator.getResourceString("easyshell.command.page.button.tooltip.remove")); + removeButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + removeDialog(); + } + }); + removeButton.setLayoutData(gridData); + removeButton.setFont(font); + setButtonLayoutData(removeButton); + } + + private void createEditButton(Font font, GridData gridData, Composite groupComponent) { + editButton = new Button(groupComponent, SWT.PUSH); + editButton.setText(Activator.getResourceString("easyshell.command.page.button.text.edit")); + editButton.setToolTipText(Activator.getResourceString("easyshell.command.page.button.tooltip.edit")); + editButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + editDialog(); + } + }); + editButton.setLayoutData(gridData); + editButton.setFont(font); + setButtonLayoutData(editButton); + } + + private void createCopyButton(Font font, GridData gridData, Composite groupComponent) { + addCopyButton = new Button(groupComponent, SWT.PUSH); + addCopyButton.setText(Activator.getResourceString("easyshell.command.page.button.text.copy")); + addCopyButton.setToolTipText(Activator.getResourceString("easyshell.command.page.button.tooltip.copy")); + addCopyButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + addCopyDialog(); + } + }); + addCopyButton.setLayoutData(gridData); + addCopyButton.setFont(font); + setButtonLayoutData(addCopyButton); + } + + private void createNewButton(Font font, GridData gridData, Composite groupComponent) { + addNewButton = new Button(groupComponent, SWT.PUSH); + addNewButton.setText(Activator.getResourceString("easyshell.command.page.button.text.new")); + addNewButton.setToolTipText(Activator.getResourceString("easyshell.command.page.button.tooltip.new")); + addNewButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + addNewDialog(); + } + }); + addNewButton.setLayoutData(gridData); + addNewButton.setFont(font); + setButtonLayoutData(addNewButton); + } + + private void addDialog(CommandData data) { + CommandDataDialog dialog = new CommandDataDialog(getShell(), data, false); + if (dialog.open() == Window.OK) { + commandStore.add(data); + refreshTableViewer(data); + } else { + data = null; + } + } + + private void addNewDialog() { + CommandData dataNew = new CommandData(null, PresetType.presetUser, Utils.getOS(), "MyNewCommand", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOther, "my_new_command"); + addDialog(dataNew); + } + + private void addCopyDialog() { + IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection(); + CommandData dataSelected = (CommandData)selection.getFirstElement(); + CommandData dataNew = new CommandData(dataSelected, true); + dataNew.setPresetType(PresetType.presetUser); + addDialog(dataNew); + } + + private void editDialog() { + IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection(); + CommandData dataSelected = (CommandData)selection.getFirstElement(); + if (dataSelected.getPresetType() == PresetType.presetUser) { + CommandData dataNew = new CommandData(dataSelected, false); + dataNew.setPosition(dataSelected.getPosition()); + CommandDataDialog dialog = new CommandDataDialog(getShell(), dataNew, true); + if (dialog.open() == Window.OK) { + commandStore.replace(dataNew); + refreshTableViewer(dataNew); + } else { + dataNew = null; + } + } + } + + private void removeDialog() { + String title = Activator.getResourceString("easyshell.command.page.dialog.remove.title"); + String question = Activator.getResourceString("easyshell.command.page.dialog.remove.question"); + MessageDialog dialog = new MessageDialog( + null, title, null, question, + MessageDialog.QUESTION, + new String[] {"Yes", "No"}, + 1); // no is the default + int result = dialog.open(); + if (result == 0) { + IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection(); + Iterator elements = selection.iterator(); + while (elements.hasNext()) { + CommandData data = (CommandData) elements.next(); + commandStore.delete(data); + } + tableViewer.refresh(); + } + } + + private void refreshTableViewer(CommandData data) { + tableViewer.refresh(); + tableViewer.setSelection(new StructuredSelection(data)); + } + +} \ No newline at end of file diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandTableFilter.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandTableFilter.java new file mode 100644 index 00000000..a41d94ef --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandTableFilter.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; + +public class CommandTableFilter extends ViewerFilter { + + private String searchString; + + public void setSearchText(String s) { + // add pre and post fix that it can be used for case-insensitive matching + this.searchString = "(?i).*" + s + ".*"; + } + + @Override + public boolean select(Viewer viewer, Object parentElement, Object element) { + if (searchString == null || searchString.length() == 0) { + return true; + } + CommandData data = (CommandData) element; + if (data.getName().matches(searchString)) { + return true; + } + if (data.getCommand().matches(searchString)) { + return true; + } + return false; + } + +} \ No newline at end of file diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Data.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Data.java new file mode 100644 index 00000000..f8366d66 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Data.java @@ -0,0 +1,94 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +import java.util.UUID; + +public class Data implements IData { + + // internal + private int position = 0; + private String id = null; + + public Data(String id) { + if (id == null || id.isEmpty()) { + this.id = UUID.randomUUID().toString(); + } else { + this.id = id; + } + } + + public Data(String newId, IData data) { + this(newId); + } + + public Data(IData data, boolean generateNewId) { + this(generateNewId ? UUID.randomUUID().toString() : data.getId(), data); + } + + public Data(IData data) { + } + + public Data() { + } + + /* (non-Javadoc) + * @see de.anbos.eclipse.easyshell.plugin.preferences.IData#getPosition() + */ + @Override + public int getPosition() { + return position; + } + + /* (non-Javadoc) + * @see de.anbos.eclipse.easyshell.plugin.preferences.IData#getId() + */ + @Override + public String getId() { + return id; + } + + /* (non-Javadoc) + * @see de.anbos.eclipse.easyshell.plugin.preferences.IData#equals(java.lang.Object) + */ + @Override + public boolean equals(Object object) { + if(!(object instanceof Data)) { + return false; + } + IData data = (IData)object; + if( data.getId().equals(this.getId()) + /*data.getPosition() == this.getPosition()*/ + ) + { + return true; + } + return false; + } + + /* (non-Javadoc) + * @see de.anbos.eclipse.easyshell.plugin.preferences.IData#setPosition(int) + */ + @Override + public void setPosition(int position) { + this.position = position; + } + + /* (non-Javadoc) + * @see de.anbos.eclipse.easyshell.plugin.preferences.IData#setId(java.lang.String) + */ + @Override + public void setId(String id) { + this.id = id; + } + +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/DataMover.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/DataMover.java new file mode 100644 index 00000000..47873bda --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/DataMover.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +public class DataMover { + + private IDataStore store; + private IData data; + + public DataMover(IDataStore store) { + this.store = store; + } + + public void setData(IData data) { + this.data = data; + } + + public void moveCurrentSelectionUp() { + if(data == null) { + return; + } + IData previousElement = store.getPreviousElement(data); + if(previousElement == null) { + return; + } + int newPosition = previousElement.getPosition(); + int oldPosition = data.getPosition(); + previousElement.setPosition(oldPosition); + data.setPosition(newPosition); + } + + public void moveCurrentSelectionDown() { + if(data == null) { + return; + } + IData nextElement = store.getNextElement(data); + if(nextElement == null) { + return; + } + int newPosition = nextElement.getPosition(); + int oldPosition = data.getPosition(); + nextElement.setPosition(oldPosition); + data.setPosition(newPosition); + } +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/DataStore.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/DataStore.java new file mode 100644 index 00000000..0c0e762e --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/DataStore.java @@ -0,0 +1,201 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import org.eclipse.jface.preference.IPreferenceStore; + +import de.anbos.eclipse.easyshell.plugin.Constants; + +public class DataStore implements IDataStore { + + private IPreferenceStore store; + private List items; + private DataObjectComparator comparator; + + public DataStore(IPreferenceStore store) { + this.items = new ArrayList(); + this.store = store; + } + + public List getDataList() { + return items; + } + + /* (non-Javadoc) + * @see de.anbos.eclipse.easyshell.plugin.preferences.IDataStore#getPreviousElement(de.anbos.eclipse.easyshell.plugin.preferences.IData) + */ + @Override + public IData getPreviousElement(IData data) { + sort(); + for(int i = 0 ; i < items.size() ; i++) { + IData item = (IData)items.get(i); + if(item.equals(data)) { + try { + return (IData)items.get(i - 1); + } catch(Throwable t) { + return null; + } + } + } + return null; + } + + /* (non-Javadoc) + * @see de.anbos.eclipse.easyshell.plugin.preferences.IDataStore#getNextElement(de.anbos.eclipse.easyshell.plugin.preferences.IData) + */ + @Override + public IData getNextElement(IData data) { + sort(); + for(int i = 0 ; i < items.size() ; i++) { + IData item = (IData)items.get(i); + if(item.equals(data)) { + try { + return (IData)items.get(i + 1); + } catch(Throwable t) { + return null; + } + } + } + return null; + } + + /* (non-Javadoc) + * @see de.anbos.eclipse.easyshell.plugin.preferences.IDataStore#getLastElement() + */ + @Override + public IData getLastElement() { + sort(); + int index = items.size() - 1; + if(index < 0) { + return null; + } + return (IData)items.get(index); + } + + public void add(T data) { + int position = 0; + IData lastElement = getLastElement(); + if(lastElement != null) { + position = lastElement.getPosition() + 1; + } + data.setPosition(position); + items.add(data); + sort(); + } + + public void replace(T data) { + items.set(data.getPosition(), data); + //sort(); + } + + public void delete(IData data) { + items.remove(data); + sort(); + } + + /* (non-Javadoc) + * @see de.anbos.eclipse.easyshell.plugin.preferences.IDataStore#save() + */ + @Override + public void save() { + } + + /* (non-Javadoc) + * @see de.anbos.eclipse.easyshell.plugin.preferences.IDataStore#loadDefaults() + */ + @Override + public void loadDefaults() { + load(); + } + + /* (non-Javadoc) + * @see de.anbos.eclipse.easyshell.plugin.preferences.IDataStore#load() + */ + @Override + public void load() { + sort(); + } + + /* (non-Javadoc) + * @see de.anbos.eclipse.easyshell.plugin.preferences.IDataStore#removeAll() + */ + @Override + public void removeAll() { + items.clear(); + } + + /* (non-Javadoc) + * @see de.anbos.eclipse.easyshell.plugin.preferences.IDataStore#isMigrated() + */ + @Override + public boolean isMigrated() { + return store.getBoolean(Constants.PREF_MIGRATED); + } + + /* (non-Javadoc) + * @see de.anbos.eclipse.easyshell.plugin.preferences.IDataStore#setMigrated(boolean) + */ + @Override + public void setMigrated(boolean migrated) { + store.setValue(Constants.PREF_MIGRATED, migrated); + } + + public T getByPosition(int position) { + return items.get(position); + } + + protected IPreferenceStore getStore() { + return store; + } + + protected void addItem(T data) { + items.add(data); + } + + protected void sort() { + if(comparator == null) { + comparator = new DataObjectComparator(); + } + Collections.sort(items, comparator); + for (int i=0;i { + public int compare(Object object1, Object object2) { + IData data1 = null; + IData data2 = null; + data1 = (IData)object1; + data2 = (IData)object2; + if(data1 == null || data2 == null) { + return -1; + } + if(data1.getPosition() > data2.getPosition()) { + return 1; + } + if(data1.getPosition() == data2.getPosition()) { + return 0; + } + if(data1.getPosition() < data2.getPosition()) { + return -1; + } + return -1; + } + } + +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/IData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/IData.java new file mode 100644 index 00000000..faffca0e --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/IData.java @@ -0,0 +1,15 @@ +package de.anbos.eclipse.easyshell.plugin.preferences; + +public interface IData { + + int getPosition(); + + String getId(); + + boolean equals(Object object); + + void setPosition(int position); + + void setId(String id); + +} \ No newline at end of file diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/IDataStore.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/IDataStore.java new file mode 100644 index 00000000..409ee868 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/IDataStore.java @@ -0,0 +1,23 @@ +package de.anbos.eclipse.easyshell.plugin.preferences; + +public interface IDataStore { + + IData getPreviousElement(IData data); + + IData getNextElement(IData data); + + IData getLastElement(); + + void save(); + + void loadDefaults(); + + void load(); + + void removeAll(); + + boolean isMigrated(); + + void setMigrated(boolean migrated); + +} \ No newline at end of file diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MainPage.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MainPage.java new file mode 100644 index 00000000..8c87e43e --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MainPage.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +import org.eclipse.jface.preference.PreferencePage; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; + +public class MainPage extends PreferencePage implements IWorkbenchPreferencePage { + + public MainPage() { + // TODO Auto-generated constructor stub + } + + public MainPage(String title) { + super(title); + // TODO Auto-generated constructor stub + } + + public MainPage(String title, ImageDescriptor image) { + super(title, image); + // TODO Auto-generated constructor stub + } + + @Override + public void init(IWorkbench workbench) { + // TODO Auto-generated method stub + + } + + @Override + protected Control createContents(Composite parent) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java index 9854d39e..e64f1edc 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java @@ -17,11 +17,7 @@ import de.anbos.eclipse.easyshell.plugin.types.MenuNameType; import de.anbos.eclipse.easyshell.plugin.types.Version; -public class MenuData { - - // internal - private int position = 0; - private String id = null; +public class MenuData extends Data { // menu private boolean enabled = true; @@ -31,11 +27,7 @@ public class MenuData { private CommandData commandData = null; public MenuData(String id, boolean enabled, MenuNameType nameType, String namePattern, CommandData commandData) { - if (id == null || id.isEmpty()) { - this.id = UUID.randomUUID().toString(); - } else { - this.id = id; - } + super(id); this.enabled = enabled; this.nameType = nameType; this.namePattern = namePattern; @@ -43,7 +35,7 @@ public MenuData(String id, boolean enabled, MenuNameType nameType, String namePa } public MenuData(String newId, CommandData commandData) { - this.id = newId; + super(newId); setNameType(MenuNameType.menuNameTypeGeneric1); setCommandData(commandData); } @@ -65,18 +57,10 @@ public MenuData(MenuData data, boolean generateNewId) { public MenuData() { } - public int getPosition() { - return position; - } - public boolean isEnabled() { return enabled; } - public String getId() { - return id; - } - public MenuNameType getNameType() { return nameType; } @@ -173,18 +157,10 @@ public String serialize(String delimiter) { return serialize(Version.actual, delimiter); } - public void setPosition(int position) { - this.position = position; - } - public void setEnabled(boolean enabled) { this.enabled = enabled; } - public void setId(String id) { - this.id = id; - } - public void setNameType(MenuNameType nameType) { this.nameType = nameType; if (nameType != MenuNameType.menuNameTypeUser) { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataMover.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataMover.java index 8db38381..075ac7da 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataMover.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataMover.java @@ -16,45 +16,14 @@ import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableItem; -public class MenuDataMover implements SelectionListener { +public class MenuDataMover extends DataMover implements SelectionListener { - private Table table; - private MenuDataStore store; + private Table table; - private MenuData currentSelection; - - public MenuDataMover(Table table, MenuDataStore store) { - this.table = table; - this.store = store; - table.addSelectionListener(this); - } - - public void moveCurrentSelectionUp() { - if(currentSelection == null) { - return; - } - MenuData previousElement = store.getPreviousElement(currentSelection); - if(previousElement == null) { - return; - } - int newPosition = previousElement.getPosition(); - int oldPosition = currentSelection.getPosition(); - previousElement.setPosition(oldPosition); - currentSelection.setPosition(newPosition); - } - - public void moveCurrentSelectionDown() { - if(currentSelection == null) { - return; - } - MenuData nextElement = store.getNextElement(currentSelection); - if(nextElement == null) { - return; - } - int newPosition = nextElement.getPosition(); - int oldPosition = currentSelection.getPosition(); - nextElement.setPosition(oldPosition); - currentSelection.setPosition(newPosition); + public MenuDataMover(Table table, IDataStore store) { + super(store); + this.table = table; + this.table.addSelectionListener(this); } public void widgetDefaultSelected(SelectionEvent e) { @@ -65,13 +34,13 @@ public void widgetSelected(SelectionEvent e) { try { item = table.getSelection()[0]; } catch(Throwable t) { - currentSelection = null; + setData(null); return; } if(item == null || !(item.getData() instanceof MenuData)) { - currentSelection = null; + setData(null); return; } - currentSelection = (MenuData)item.getData(); + setData((IData)item.getData()); } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java index 42405de5..2e25aa8e 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java @@ -12,8 +12,6 @@ package de.anbos.eclipse.easyshell.plugin.preferences; import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; import java.util.Iterator; import java.util.List; @@ -21,23 +19,14 @@ import de.anbos.eclipse.easyshell.plugin.Constants; -public class MenuDataStore { - - private IPreferenceStore store; - private List items; - private DataObjectComparator comparator; +public class MenuDataStore extends DataStore { public MenuDataStore(IPreferenceStore store) { - items = new ArrayList(); - this.store = store; - } - - public List getCommandMenuDataList() { - return items; + super(store); } public MenuData[] getCommandMenuDataArray() { - List allItems = getCommandMenuDataList(); + List allItems = getDataList(); if(allItems.size() <= 0) { return new MenuData[0]; } @@ -50,7 +39,7 @@ public MenuData[] getCommandMenuDataArray() { public List getEnabledCommandMenuDataList() { List checkedItems = new ArrayList(); - Iterator dataIterator = items.iterator(); + Iterator dataIterator = getDataList().iterator(); while(dataIterator.hasNext()) { MenuData data = (MenuData)dataIterator.next(); if(data.isEnabled()) { @@ -72,130 +61,22 @@ public MenuData[] getEnabledCommandMenuDataArray() { return checked; } - public MenuData getPreviousElement(MenuData data) { - sort(); - for(int i = 0 ; i < items.size() ; i++) { - MenuData item = (MenuData)items.get(i); - if(item.equals(data)) { - try { - return (MenuData)items.get(i - 1); - } catch(Throwable t) { - return null; - } - } - } - return null; - } - - public MenuData getNextElement(MenuData data) { - sort(); - for(int i = 0 ; i < items.size() ; i++) { - MenuData item = (MenuData)items.get(i); - if(item.equals(data)) { - try { - return (MenuData)items.get(i + 1); - } catch(Throwable t) { - return null; - } - } - } - return null; - } - - public MenuData getLastElement() { - sort(); - int index = items.size() - 1; - if(index < 0) { - return null; - } - return (MenuData)items.get(index); - } - - public void add(MenuData data) { - int position = 0; - MenuData lastElement = getLastElement(); - if(lastElement != null) { - position = lastElement.getPosition() + 1; - } - data.setPosition(position); - items.add(data); - sort(); - } - - public void replace(MenuData data) { - items.set(data.getPosition(), data); - //sort(); - } - - public void delete(MenuData data) { - items.remove(data); - sort(); - } - public void save() { - store.setValue(Constants.PREF_MENU,PreferenceValueConverter.asMenuDataString(getCommandMenuDataList())); + getStore().setValue(Constants.PREF_MENU,PreferenceValueConverter.asMenuDataString(getDataList())); } public void loadDefaults() { - store.setToDefault(Constants.PREF_MENU); + getStore().setToDefault(Constants.PREF_MENU); load(); } public void load() { - MenuData[] items = PreferenceValueConverter.asMenuDataArray(store.getString(Constants.PREF_MENU)); - this.items.clear(); + MenuData[] items = PreferenceValueConverter.asMenuDataArray(getStore().getString(Constants.PREF_MENU)); + removeAll(); for(int i = 0 ; i < items.length ; i++) { - this.items.add(items[i]); + addItem(items[i]); } sort(); } - public void removeAll() { - items.clear(); - } - - public boolean isMigrated() { - return store.getBoolean(Constants.PREF_MIGRATED); - } - - public void setMigrated(boolean migrated) { - store.setValue(Constants.PREF_MIGRATED, migrated); - } - - private void sort() { - if(comparator == null) { - comparator = new DataObjectComparator(); - } - Collections.sort(items,comparator); - for (int i=0;i { - public int compare(Object object1, Object object2) { - MenuData data1 = null; - MenuData data2 = null; - if(object1 instanceof MenuData) { - data1 = (MenuData)object1; - } - if(object2 instanceof MenuData) { - data2 = (MenuData)object2; - } - if(data1 == null || data2 == null) { - return -1; - } - if(data1.getPosition() > data2.getPosition()) { - return 1; - } - if(data1.getPosition() == data2.getPosition()) { - return 0; - } - if(data1.getPosition() < data2.getPosition()) { - return -1; - } - return -1; - } - } - } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsPage.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java similarity index 64% rename from plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsPage.java rename to plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java index 27ed066d..5b86593f 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandsPage.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java @@ -14,7 +14,6 @@ import java.util.Iterator; import java.util.List; -import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.CheckStateChangedEvent; import org.eclipse.jface.viewers.CheckboxTableViewer; @@ -25,12 +24,14 @@ import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TableViewerColumn; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerSorter; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ControlAdapter; -import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Font; @@ -40,23 +41,24 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.Text; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; import de.anbos.eclipse.easyshell.plugin.Activator; -public class CommandsPage extends org.eclipse.jface.preference.PreferencePage +public class MenuPage extends org.eclipse.jface.preference.PreferencePage implements IWorkbenchPreferencePage { - private static final int TABLE_WIDTH = 400; - - private Table table; - private MenuDataMover itemMover; - private CommandDataStore cmdStore; - List cmdList; + private CommandDataStore commandStore; + List commandList; private MenuDataStore menuStore; + private MenuDataMover itemMover; + private Text searchText; + private MenuTableFilter filter; private CheckboxTableViewer tableViewer; private Button addNewButton; private Button addCopyButton; @@ -73,8 +75,8 @@ public void init(IWorkbench workbench) { public boolean performOk() { boolean save = true; if (!menuStore.isMigrated()) { - String title = Activator.getResourceString("easyshell.page.table.dialog.migration.title"); - String question = Activator.getResourceString("easyshell.page.table.dialog.migration.question"); + String title = Activator.getResourceString("easyshell.menu.page.dialog.migration.title"); + String question = Activator.getResourceString("easyshell.menu.page.dialog.migration.question"); MessageDialog dialog = new MessageDialog( null, title, null, question, MessageDialog.WARNING, @@ -95,8 +97,8 @@ public boolean performOk() { @Override protected void performDefaults() { - String title = Activator.getResourceString("easyshell.page.table.dialog.defaults.title"); - String question = Activator.getResourceString("easyshell.page.table.dialog.defaults.question"); + String title = Activator.getResourceString("easyshell.menu.page.dialog.defaults.title"); + String question = Activator.getResourceString("easyshell.menu.page.dialog.defaults.question"); MessageDialog dialog = new MessageDialog( null, title, null, question, MessageDialog.WARNING, @@ -106,7 +108,7 @@ protected void performDefaults() { if (result == 0) { menuStore.loadDefaults(); tableViewer.refresh(); - for (MenuData item : menuStore.getCommandMenuDataList()) { + for (MenuData item : menuStore.getDataList()) { tableViewer.setChecked(item, true); } } @@ -119,54 +121,127 @@ protected void performApply() { @Override protected Control createContents(Composite parent) { - Font font = parent.getFont(); - // define default grid + // main page composite Composite pageComponent = new Composite(parent, SWT.NONE); - GridLayout layout = new GridLayout(); - layout.numColumns = 2; - layout.marginWidth = 0; - layout.marginHeight = 0; + GridLayout layout = new GridLayout(3, false); pageComponent.setLayout(layout); + //parent.setLayout(layout); - // list - GridData gridData = new GridData(GridData.FILL_BOTH); - // create table - table = new Table(pageComponent, SWT.MULTI | SWT.CHECK | SWT.FULL_SELECTION); - table.setHeaderVisible(true); - table.setLinesVisible(true); - table.setFont(parent.getFont()); - - TableColumn column1 = new TableColumn(table, SWT.LEFT); - column1.setText(Activator.getResourceString("easyshell.page.table.header.title.column0")); //$NON-NLS-1$ - column1.setResizable(false); - - TableColumn column2 = new TableColumn(table, SWT.LEFT); - column2.setText(Activator.getResourceString("easyshell.page.table.header.title.column1")); //$NON-NLS-1$ - column2.setResizable(false); - - int availableRows = availableRows(pageComponent); - gridData.heightHint = table.getItemHeight() * (availableRows / 8); - gridData.widthHint = TABLE_WIDTH; - table.setLayoutData(gridData); - - tableViewer = new CheckboxTableViewer(table); - tableViewer.setLabelProvider(new MenuDataLabelProvider()); - tableViewer.setContentProvider(new MenuDataContentProvider()); + // search + createSearchField(pageComponent); // command store - cmdStore = new CommandDataStore(Activator.getDefault().getPreferenceStore()); - cmdStore.load(); + commandStore = new CommandDataStore(Activator.getDefault().getPreferenceStore()); + commandStore.load(); // get the native commands list - cmdList = CommandDataDefaultCollection.getCommandsNative(cmdStore.getAllCommands(), true); + commandList = CommandDataDefaultCollection.getCommandsNative(commandStore.getDataList(), true); // menu store menuStore = new MenuDataStore(Activator.getDefault().getPreferenceStore()); menuStore.load(); + + // table viewer + createTableViewer(pageComponent); + + // buttons + createButtons(pageComponent); + + // send event to refresh tableViewer + Event event = new Event(); + event.item = null; + tableViewer.refresh(); + tableViewer.getTable().notifyListeners(SWT.Selection, event); + + return pageComponent; + } + + private void createSearchField(Composite parent) { + /* + Group group = new Group(parent, SWT.SHADOW_ETCHED_IN); + group.setText(Activator.getResourceString("easyshell.command.page.text.text.search")); + group.setToolTipText(Activator.getResourceString("easyshell.command.page.text.tooltip.search")); + GridLayout layout2 = new GridLayout(); + layout2.numColumns = 1; + layout2.makeColumnsEqualWidth = false; + layout2.marginWidth = 5; + layout2.marginHeight = 4; + group.setLayout(layout2); + GridData data2 = new GridData(GridData.FILL_HORIZONTAL); + group.setLayoutData(data2); + group.setFont(parent.getFont());*/ + + //Label searchLabel = new Label(parent, SWT.NONE); + //searchLabel.setText("Search: "); + filter = new MenuTableFilter(); + searchText = new Text(parent, SWT.BORDER | SWT.SEARCH); + searchText.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL + | GridData.HORIZONTAL_ALIGN_FILL)); + searchText.addKeyListener(new KeyAdapter() { + public void keyReleased(KeyEvent ke) { + filter.setSearchText(searchText.getText()); + tableViewer.refresh(); + } + + }); + searchText.setToolTipText(Activator.getResourceString("easyshell.command.page.text.tooltip.search")); + // fake + Label label = new Label(parent, SWT.NONE); + label.setText(""); + } + + private void createButtons(Composite pageComponent) { + Font font = pageComponent.getFont(); + // button pageComponent + Composite groupComponent = new Composite(pageComponent, SWT.NULL); + GridLayout groupLayout = new GridLayout(); + groupLayout.marginWidth = 0; + groupLayout.marginHeight = 0; + groupComponent.setLayout(groupLayout); + GridData gridData = new GridData(); + gridData.verticalAlignment = GridData.FILL; + gridData.horizontalAlignment = GridData.FILL; + groupComponent.setLayoutData(gridData); + groupComponent.setFont(font); + + // buttons + createNewButton(font, gridData, groupComponent); + createCopyButton(font, gridData, groupComponent); + createEditButton(font, gridData, groupComponent); + createRemoveButton(font, gridData, groupComponent); + createUpButton(font, gridData, groupComponent); + createDownButton(font, gridData, groupComponent); + } + + private void createTableViewer(Composite parent) { + tableViewer = CheckboxTableViewer.newCheckList(parent, SWT.MULTI | SWT.H_SCROLL + | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER); + createColumns(parent, tableViewer); + final Table table = tableViewer.getTable(); + table.setHeaderVisible(true); + table.setLinesVisible(true); + + tableViewer.setLabelProvider(new MenuDataLabelProvider()); + tableViewer.setContentProvider(new MenuDataContentProvider()); + tableViewer.addFilter(filter); + + // Get the content for the viewer, setInput will call getElements in the + // contentProvider tableViewer.setInput(menuStore); + + // update/set checked elements tableViewer.setAllChecked(false); tableViewer.setCheckedElements(menuStore.getEnabledCommandMenuDataArray()); + // Layout the viewer + GridData gridData = new GridData(); + gridData.verticalAlignment = GridData.FILL; + gridData.horizontalSpan = 2; + gridData.grabExcessHorizontalSpace = true; + gridData.grabExcessVerticalSpace = true; + gridData.horizontalAlignment = GridData.FILL; + tableViewer.getControl().setLayoutData(gridData); + tableViewer.addDoubleClickListener(new IDoubleClickListener() { @Override public void doubleClick(DoubleClickEvent event) { @@ -220,52 +295,30 @@ public boolean isSorterProperty(Object element, String property) { }); itemMover = new MenuDataMover(table, menuStore); - - // button pageComponent - Composite groupComponent = new Composite(pageComponent, SWT.NULL); - GridLayout groupLayout = new GridLayout(); - groupLayout.marginWidth = 0; - groupLayout.marginHeight = 0; - groupComponent.setLayout(groupLayout); - gridData = new GridData(); - gridData.verticalAlignment = GridData.FILL; - gridData.horizontalAlignment = GridData.FILL; - groupComponent.setLayoutData(gridData); - groupComponent.setFont(font); - - // buttons - createNewButton(font, gridData, groupComponent); - - createCopyButton(font, gridData, groupComponent); - - createEditButton(font, gridData, groupComponent); - - createRemoveButton(font, gridData, groupComponent); - - createUpButton(font, gridData, groupComponent); - - createDownButton(font, gridData, groupComponent); - - configureTableResizing(table); - - Dialog.applyDialogFont(pageComponent); - // trigger the resize - table.getHorizontalBar().setVisible(true); - - // send event to refresh tableViewer - Event event = new Event(); - event.item = null; - tableViewer.refresh(); - tableViewer.getTable().notifyListeners(SWT.Selection, event); - //tableViewer.getControl().setEnabled(true); - - return pageComponent; + } + + private void createColumns(final Composite parent, final TableViewer viewer) { + TableViewerColumn viewerColumn1 = new TableViewerColumn(viewer, + SWT.NONE); + TableColumn column1 = viewerColumn1.getColumn(); + column1.setText(Activator.getResourceString("easyshell.menu.page.header.title.column0")); + column1.setWidth(200); + column1.setResizable(true); + column1.setMoveable(true); + + TableViewerColumn viewerColumn2 = new TableViewerColumn(viewer, + SWT.NONE); + TableColumn column2 = viewerColumn2.getColumn(); + column2.setText(Activator.getResourceString("easyshell.menu.page.header.title.column1")); + column2.setWidth(400); + column2.setResizable(true); + column2.setMoveable(true); } private void createDownButton(Font font, GridData gridData, Composite groupComponent) { downButton = new Button(groupComponent, SWT.PUSH); - downButton.setText(Activator.getResourceString("easyshell.page.table.button.text.down")); - downButton.setToolTipText(Activator.getResourceString("easyshell.page.table.button.tooltip.down")); + downButton.setText(Activator.getResourceString("easyshell.menu.page.button.text.down")); + downButton.setToolTipText(Activator.getResourceString("easyshell.menu.page.button.tooltip.down")); downButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { @@ -279,8 +332,8 @@ public void widgetSelected(SelectionEvent event) { private void createUpButton(Font font, GridData gridData, Composite groupComponent) { upButton = new Button(groupComponent, SWT.PUSH); - upButton.setText(Activator.getResourceString("easyshell.page.table.button.text.up")); - upButton.setToolTipText(Activator.getResourceString("easyshell.page.table.button.tooltip.up")); + upButton.setText(Activator.getResourceString("easyshell.menu.page.button.text.up")); + upButton.setToolTipText(Activator.getResourceString("easyshell.menu.page.button.tooltip.up")); upButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { @@ -294,8 +347,8 @@ public void widgetSelected(SelectionEvent event) { private void createRemoveButton(Font font, GridData gridData, Composite groupComponent) { removeButton = new Button(groupComponent, SWT.PUSH); - removeButton.setText(Activator.getResourceString("easyshell.page.table.button.text.remove")); - removeButton.setToolTipText(Activator.getResourceString("easyshell.page.table.button.tooltip.remove")); + removeButton.setText(Activator.getResourceString("easyshell.menu.page.button.text.remove")); + removeButton.setToolTipText(Activator.getResourceString("easyshell.menu.page.button.tooltip.remove")); removeButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { @@ -309,8 +362,8 @@ public void widgetSelected(SelectionEvent event) { private void createEditButton(Font font, GridData gridData, Composite groupComponent) { editButton = new Button(groupComponent, SWT.PUSH); - editButton.setText(Activator.getResourceString("easyshell.page.table.button.text.edit")); - editButton.setToolTipText(Activator.getResourceString("easyshell.page.table.button.tooltip.edit")); + editButton.setText(Activator.getResourceString("easyshell.menu.page.button.text.edit")); + editButton.setToolTipText(Activator.getResourceString("easyshell.menu.page.button.tooltip.edit")); editButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { @@ -324,8 +377,8 @@ public void widgetSelected(SelectionEvent event) { private void createCopyButton(Font font, GridData gridData, Composite groupComponent) { addCopyButton = new Button(groupComponent, SWT.PUSH); - addCopyButton.setText(Activator.getResourceString("easyshell.page.table.button.text.copy")); - addCopyButton.setToolTipText(Activator.getResourceString("easyshell.page.table.button.tooltip.copy")); + addCopyButton.setText(Activator.getResourceString("easyshell.menu.page.button.text.copy")); + addCopyButton.setToolTipText(Activator.getResourceString("easyshell.menu.page.button.tooltip.copy")); addCopyButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { @@ -339,8 +392,8 @@ public void widgetSelected(SelectionEvent event) { private void createNewButton(Font font, GridData gridData, Composite groupComponent) { addNewButton = new Button(groupComponent, SWT.PUSH); - addNewButton.setText(Activator.getResourceString("easyshell.page.table.button.text.new")); - addNewButton.setToolTipText(Activator.getResourceString("easyshell.page.table.button.tooltip.new")); + addNewButton.setText(Activator.getResourceString("easyshell.menu.page.button.text.new")); + addNewButton.setToolTipText(Activator.getResourceString("easyshell.menu.page.button.tooltip.new")); addNewButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { @@ -352,119 +405,26 @@ public void widgetSelected(SelectionEvent event) { setButtonLayoutData(addNewButton); } - private int availableRows(Composite parent) { - int fontHeight = (parent.getFont().getFontData())[0].getHeight(); - int displayHeight = parent.getDisplay().getClientArea().height; - return displayHeight / fontHeight; - } - - /** - * Correctly resizes the table so no phantom columns appear - * - * @param table the table - * @since 3.1 - */ - private void configureTableResizing(final Table table) { - ControlAdapter resizer = new ControlAdapter() { - private boolean fIsResizing = false; - // private final int[] fWidths= {100, 70, 70, 130, 45}; - private final int[] fWidths = { 120, 280}; - private int fSum = TABLE_WIDTH; - - public void controlResized(ControlEvent e) { - if (fIsResizing) - return; - try { - fIsResizing = true; - int clientAreaWidth = table.getClientArea().width; - TableColumn[] columns = table.getColumns(); - int calculatedtableWidth = 0; - - if (e.widget == table) { - int initial[] = { 120, 280 }; - int minimums[] = new int[columns.length]; - int minSum = 0; - for (int i = 0; i < columns.length; i++) { - // don't make a column narrower than the minimum, - // or than what it is currently if less than the minimum - minimums[i] = Math.min(fWidths[i], initial[i]); - minSum += minimums[i]; - } - - int newWidth = fSum < clientAreaWidth ? clientAreaWidth : Math.max(clientAreaWidth, minSum); - final int toDistribute = newWidth - fSum; - int lastPart = toDistribute; - if (toDistribute != 0) { - int[] iteration = { 0, 1 }; // give the description column all the rest - for (int i = 0; i < iteration.length; i++) { - int c = iteration[i]; - int width; - if (fSum > 0) { - int part; - if (i == iteration.length - 1) - part = lastPart; - else - // current width is the weight for the distribution of the extra space - part = toDistribute * fWidths[c] / fSum; - lastPart -= part; - width = Math.max(minimums[c], fWidths[c] + part); - } else { - width = toDistribute * initial[c] / TABLE_WIDTH; - } - columns[c].setWidth(width); - fWidths[c] = width; - calculatedtableWidth += width; - } - fSum = calculatedtableWidth; - } - } else { - // column being resized - // on GTK, the last column gets auto-adapted - ignore this - if (e.widget == columns[2]) - return; - for (int i = 0; i < columns.length; i++) { - fWidths[i] = columns[i].getWidth(); - calculatedtableWidth += fWidths[i]; - } - fSum = calculatedtableWidth; - } - - // set scroll bar visible - table.getHorizontalBar().setVisible(calculatedtableWidth > clientAreaWidth); - } finally { - fIsResizing = false; - } - } - }; - table.addControlListener(resizer); - TableColumn[] columns = table.getColumns(); - for (int i = 0; i < columns.length; i++) { - columns[i].addControlListener(resizer); + private void addDialog(MenuData data) { + MenuDataDialog dialog = new MenuDataDialog(getShell(), data, commandStore, commandList, false); + if (dialog.open() == Window.OK) { + menuStore.add(data); + refreshTableViewer(data); + } else { + data = null; } } private void addNewDialog() { - MenuData dataNew = new MenuData(cmdList.get(0), true); - MenuDataDialog dialog = new MenuDataDialog(getShell(), dataNew, cmdStore, cmdList, false); - if (dialog.open() == Window.OK) { - menuStore.add(dataNew); - refreshTableViewer(dataNew); - } else { - dataNew = null; - } + MenuData dataNew = new MenuData(commandList.get(0), true); + addDialog(dataNew); } private void addCopyDialog() { IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection(); MenuData dataSelected = (MenuData)selection.getFirstElement(); MenuData dataNew = new MenuData(dataSelected, true); - MenuDataDialog dialog = new MenuDataDialog(getShell(), dataNew, cmdStore, cmdList, false); - if (dialog.open() == Window.OK) { - menuStore.add(dataNew); - refreshTableViewer(dataNew); - } else { - dataNew = null; - } + addDialog(dataNew); } private void editDialog() { @@ -472,19 +432,18 @@ private void editDialog() { MenuData dataSelected = (MenuData)selection.getFirstElement(); MenuData dataNew = new MenuData(dataSelected, false); dataNew.setPosition(dataSelected.getPosition()); - MenuDataDialog dialog = new MenuDataDialog(getShell(), dataNew, cmdStore, cmdList, true); + MenuDataDialog dialog = new MenuDataDialog(getShell(), dataNew, commandStore, commandList, true); if (dialog.open() == Window.OK) { menuStore.replace(dataNew); refreshTableViewer(dataNew); } else { dataNew = null; } - } private void removeDialog() { - String title = Activator.getResourceString("easyshell.page.table.dialog.remove.title"); - String question = Activator.getResourceString("easyshell.page.table.dialog.remove.question"); + String title = Activator.getResourceString("easyshell.menu.page.dialog.remove.title"); + String question = Activator.getResourceString("easyshell.menu.page.dialog.remove.question"); MessageDialog dialog = new MessageDialog( null, title, null, question, MessageDialog.QUESTION, diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuTableFilter.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuTableFilter.java new file mode 100644 index 00000000..6cde154e --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuTableFilter.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; + +public class MenuTableFilter extends ViewerFilter { + + private String searchString; + + public void setSearchText(String s) { + // add pre and post fix that it can be used for case-insensitive matching + this.searchString = "(?i).*" + s + ".*"; + } + + @Override + public boolean select(Viewer viewer, Object parentElement, Object element) { + if (searchString == null || searchString.length() == 0) { + return true; + } + MenuData data = (MenuData) element; + if (data.getNameExpanded().matches(searchString)) { + return true; + } + if (data.getCommandData().getName().matches(searchString)) { + return true; + } + if (data.getCommandData().getCommand().matches(searchString)) { + return true; + } + return false; + } + +} \ No newline at end of file diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Version.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Version.java index 104e425c..3c9f87db 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Version.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Version.java @@ -15,12 +15,14 @@ import java.util.List; public enum Version { + // do not delete any versions and append new versions! vUnknown(-1, "Unknown"), v1_4(0, "v1.4.x"), v2_0_001(1, "v2.0 beta 1"), v2_0_002(2, "v2.0 beta 2"), v2_0_003(3, "v2.0 beta 3"); - public static Version actual = v2_0_003; + // actual version is always the last one! + public static Version actual = Version.values()[Version.values().length-1]; // attributes private final int id; private final String name; From 05c76c0b719c8ce61c670071a3c6b115e11b2959 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Sun, 24 Jul 2016 17:34:30 +0200 Subject: [PATCH 21/73] #67 [v2.0] linux presets are not automatically added fixed /added too: - #22 add Pantheon Terminal to linux presets - #24 add linux 'pantheon' file browser Signed-off-by: Andre Bossert --- .../anbos/eclipse/easyshell/plugin/Utils.java | 68 ++++++---------- .../CommandDataDefaultCollection.java | 78 ++++++++++++++----- uuids.txt | 6 +- 3 files changed, 84 insertions(+), 68 deletions(-) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/Utils.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/Utils.java index de1635a7..c7fdbf3c 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/Utils.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/Utils.java @@ -103,9 +103,9 @@ public static LinuxDesktop detectDesktopSession() { desktops.put("cinnamon", LinuxDesktop.desktopCinnamon); desktops.put("xfce", LinuxDesktop.desktopXfce); // execute - String desktop = Utils.isExpectedCommandOutput(command, desktops, true); - if (desktop != null && !desktop.isEmpty()) { - return (LinuxDesktop)desktops.get(desktop); + Object desktop = Utils.isExpectedCommandOutput(command, desktops); + if (desktop != null) { + return (LinuxDesktop)desktop; } return LinuxDesktop.desktopUnknown; } @@ -113,32 +113,23 @@ public static LinuxDesktop detectDesktopSession() { /** * detects programs from $DESKTOP_SESSION */ - public static String detectLinuxDefaultFileBrowser() { + public static Object detectLinuxDefaultFileBrowser(Map fileBrowsers) { ArrayList command = new ArrayList(); command.add("xdg-mime"); command.add("query"); command.add("default"); command.add("inode/directory"); // fill the map - Map fileBrowsers = new HashMap(); - fileBrowsers.put("nemo.desktop", "nemo"); - // execute - String fileBrowser = Utils.isExpectedCommandOutput(command, fileBrowsers, true); - if (fileBrowser != null && !fileBrowser.isEmpty()) { - return (String)fileBrowsers.get(fileBrowser); + if (fileBrowsers == null) { + fileBrowsers = new HashMap(); + fileBrowsers.put(".*", "*"); } - return null; + // execute + return Utils.isExpectedCommandOutput(command, fileBrowsers); } - /** - * Detects which desktop is used on a unix / linux system. - * - * @todo use regex - * - * @return The type of desktop. - * @see detectDesktop - */ - private static String isExpectedCommandOutput(ArrayList command, Map expectedOutput, boolean toLowerCase) { + private static Object isExpectedCommandOutput(ArrayList command, Map expectedOutput) { + Object obj = null; boolean found = false; String expectedLine = null; try { @@ -147,46 +138,35 @@ private static String isExpectedCommandOutput(ArrayList command, Map" + expectedLine + "<", null); line = null; BufferedReader err = new BufferedReader(new InputStreamReader(proc.getErrorStream())); // If there is any error output, print it to // stdout for debugging purposes while((line = err.readLine()) != null) { - //Activator.getDefault().sysout(true, "detectDesktop stderr >" + line + "<"); + Activator.logError("isExpectedCommandOutput: stderr: >" + line + "<", null); } int result = proc.waitFor(); if(result != 0) { // If there is any error code, print it to // stdout for debugging purposes - //Activator.getDefault().sysout(true, "detectDesktop return code: " + result); + Activator.logError("isExpectedCommandOutput: return code: " + result, null); } } catch(Exception e) { - e.printStackTrace(); + Activator.logError("isExpectedCommandOutput: exception", e); } - return expectedLine; + return obj; } public static void copyToClipboard(String cmdAll) { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java index 5e0be1f1..1ca8c648 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java @@ -12,8 +12,11 @@ package de.anbos.eclipse.easyshell.plugin.preferences; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import de.anbos.eclipse.easyshell.plugin.Activator; import de.anbos.eclipse.easyshell.plugin.Utils; import de.anbos.eclipse.easyshell.plugin.types.CommandType; import de.anbos.eclipse.easyshell.plugin.types.LinuxDesktop; @@ -118,6 +121,14 @@ private void addLinuxCommands() { "xfce4-terminal --working-directory=${easyshell:container_loc}")); list.add(new CommandData("adf40e10-0ee9-4abe-8282-aff7d51bb68d", PresetType.presetPlugin, OS.osLinux, "Xfce Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, "xfce4-terminal --working-directory=${easyshell:container_loc} --command=./''${easyshell:resource_name}'' --hold")); + // Linux Pantheon Terminal + list.add(new CommandData("e5b3b0f6-e27c-4a2d-aa1a-caef784dd3da", PresetType.presetPlugin, OS.osLinux, "Pantheon Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, + "pantheon-terminal --working-directory=${easyshell:container_loc}")); + list.add(new CommandData("22ec69ee-e39e-4fa6-a241-4e950d3235af", PresetType.presetPlugin, OS.osLinux, "Pantheon Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, + "pantheon-terminal --working-directory=${easyshell:container_loc} --execute=./''${easyshell:resource_name}''")); + // Linux Pantheon Filebrowser + list.add(new CommandData("025e2f56-3d2e-47e1-8daa-c2c74049b150", PresetType.presetPlugin, OS.osLinux, "Pantheon", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, + "pantheon-files ${easyshell:resource_loc}")); // Linux Nautilus list.add(new CommandData("1747b189-ed7f-4546-8c98-f99a3c1fb13b", PresetType.presetPlugin, OS.osLinux, "Nautilus", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, "nautilus ${easyshell:resource_loc}")); @@ -173,50 +184,64 @@ private static List getDefaultCommands() { case osUnknown: break; case osWindows: - listDefault.add(getCommandData(listOS, "DOS-Shell", CommandType.commandTypeOpen)); - listDefault.add(getCommandData(listOS, "DOS-Shell", CommandType.commandTypeRun)); - listDefault.add(getCommandData(listOS, "Explorer", CommandType.commandTypeExplore)); + addNotNull(listDefault, getCommandData(listOS, "DOS-Shell", CommandType.commandTypeOpen)); + addNotNull(listDefault, getCommandData(listOS, "DOS-Shell", CommandType.commandTypeRun)); + addNotNull(listDefault, getCommandData(listOS, "Explorer", CommandType.commandTypeExplore)); break; case osLinux: // try to detect the desktop LinuxDesktop desktop = Utils.detectLinuxDesktop(); //Activator.getDefault().sysout(true, "Detected linux (Unix) desktop: >" + desktop.getName() + "<"); switch (desktop) { - case desktopKde: listDefault.add(getCommandData(listOS, "KDE", CommandType.commandTypeOpen)); - listDefault.add(getCommandData(listOS, "KDE", CommandType.commandTypeRun)); - listDefault.add(getCommandData(listOS, "Dolphin", CommandType.commandTypeExplore)); + case desktopKde: addNotNull(listDefault, getCommandData(listOS, ".*KDE.*", CommandType.commandTypeOpen)); + addNotNull(listDefault, getCommandData(listOS, ".*KDE.*", CommandType.commandTypeRun)); + //addNotNull(listDefault, getCommandData(listOS, "Dolphin", CommandType.commandTypeExplore)); break; - case desktopCinnamon: listDefault.add(getCommandData(listOS, "Gnome", CommandType.commandTypeOpen)); - listDefault.add(getCommandData(listOS, "Gnome", CommandType.commandTypeRun)); - listDefault.add(getCommandData(listOS, "Nemo", CommandType.commandTypeExplore)); + case desktopCinnamon: addNotNull(listDefault, getCommandData(listOS, ".*Gnome.*", CommandType.commandTypeOpen)); + addNotNull(listDefault, getCommandData(listOS, ".*Gnome.*", CommandType.commandTypeRun)); + //addNotNull(listDefault, getCommandData(listOS, "Nemo", CommandType.commandTypeExplore)); break; - case desktopGnome: listDefault.add(getCommandData(listOS, "Gnome", CommandType.commandTypeOpen)); - listDefault.add(getCommandData(listOS, "Gnome", CommandType.commandTypeRun)); - listDefault.add(getCommandData(listOS, "Nautilus", CommandType.commandTypeExplore)); + case desktopGnome: addNotNull(listDefault, getCommandData(listOS, ".*Gnome.*", CommandType.commandTypeOpen)); + addNotNull(listDefault, getCommandData(listOS, ".*Gnome.*", CommandType.commandTypeRun)); + //addNotNull(listDefault, getCommandData(listOS, "Nautilus", CommandType.commandTypeExplore)); break; - case desktopXfce: listDefault.add(getCommandData(listOS, "Xfce", CommandType.commandTypeOpen)); - listDefault.add(getCommandData(listOS, "Xfce", CommandType.commandTypeRun)); - listDefault.add(getCommandData(listOS, "Thunar", CommandType.commandTypeExplore)); + case desktopXfce: addNotNull(listDefault, getCommandData(listOS, ".*Xfce.*", CommandType.commandTypeOpen)); + addNotNull(listDefault, getCommandData(listOS, ".*Xfce.*", CommandType.commandTypeRun)); + //addNotNull(listDefault, getCommandData(listOS, "Thunar", CommandType.commandTypeExplore)); break; default:; } // try to detect the default file browser if (desktop != LinuxDesktop.desktopUnknown) { - String fileBrowser = Utils.detectLinuxDefaultFileBrowser(); - //Activator.getDefault().sysout(true, "Detected linux (Unix) default file browser: >" + fileBrowser + "<"); + Map fileBrowsers = new HashMap(); + for (CommandData data : getCommandDataList(listOS, CommandType.commandTypeExplore)) { + fileBrowsers.put("(?i).*" + data.getName() + ".*", data); + } + Object fileBrowser = Utils.detectLinuxDefaultFileBrowser(fileBrowsers); + if (fileBrowser != null) { + CommandData data = (CommandData)fileBrowser; + Activator.logInfo("Detected linux (Unix) default file browser: >" + data.getName() + "<", null); + addNotNull(listDefault, data); + } } break; case osMacOSX: - listDefault.add(getCommandData(listOS, "Terminal", CommandType.commandTypeOpen)); - listDefault.add(getCommandData(listOS, "Terminal", CommandType.commandTypeRun)); - listDefault.add(getCommandData(listOS, "Finder", CommandType.commandTypeExplore)); + addNotNull(listDefault, getCommandData(listOS, "Terminal", CommandType.commandTypeOpen)); + addNotNull(listDefault, getCommandData(listOS, "Terminal", CommandType.commandTypeRun)); + addNotNull(listDefault, getCommandData(listOS, "Finder", CommandType.commandTypeExplore)); break; } // add clipboard - listDefault.add(getCommandData(listOS, ".*path", CommandType.commandTypeClipboard)); + addNotNull(listDefault, getCommandData(listOS, ".*path", CommandType.commandTypeClipboard)); return listDefault; } + private static void addNotNull(List list, CommandData data) { + if (data != null) { + list.add(data); + } + } + public static List getCommandData(List list, OS os, boolean sorted) { List listOut = new ArrayList(); int position = 0; @@ -242,4 +267,15 @@ private static CommandData getCommandData(List list, String name, C return null; } + private static List getCommandDataList(List list, CommandType type) { + List listOut = new ArrayList(); + for (CommandData entry : list) { + if (entry.getCommandType() == type) { + CommandData newData = new CommandData(entry, false); + listOut.add(newData); + } + } + return listOut; + } + } diff --git a/uuids.txt b/uuids.txt index 0e2dc7e7..bacb1857 100644 --- a/uuids.txt +++ b/uuids.txt @@ -27,6 +27,9 @@ e634b20a-cf57-47f0-aa27-b8fc95917f35 c6126958-32f2-4f96-9933-69ddd956f2e9 8175f9a7-4e54-4367-a6b6-251aedc187df adf40e10-0ee9-4abe-8282-aff7d51bb68d +e5b3b0f6-e27c-4a2d-aa1a-caef784dd3da +22ec69ee-e39e-4fa6-a241-4e950d3235af +025e2f56-3d2e-47e1-8daa-c2c74049b150 1747b189-ed7f-4546-8c98-f99a3c1fb13b 4fbfa632-5455-4384-9f9e-773603a12bea 8e14d26d-2981-4b81-b8e5-6a942c6f2c59 @@ -40,9 +43,6 @@ f6bcdd71-4687-46d8-bf34-2780bafd762a cd32fa5a-34d7-4551-8bd0-3aae0dc444d0 Free -e5b3b0f6-e27c-4a2d-aa1a-caef784dd3da -22ec69ee-e39e-4fa6-a241-4e950d3235af -025e2f56-3d2e-47e1-8daa-c2c74049b150 51ed300a-35d0-4e67-a5f8-6ebd7012a564 8e366a34-5ce2-4430-bc21-20e176e0128c 2a979af5-86a7-440e-b4f0-8442e85412e4 From a9118c9e1a61e86552d0a7bf3ab5408db166bce8 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Sun, 24 Jul 2016 18:03:58 +0200 Subject: [PATCH 22/73] #19 - add xdg-open for linux presets - changed icon of other/user defined type Signed-off-by: Andre Bossert --- .../de/anbos/eclipse/easyshell/plugin/Constants.java | 4 +++- .../preferences/CommandDataDefaultCollection.java | 3 +++ .../eclipse/easyshell/plugin/types/CommandType.java | 11 ++++++----- uuids.txt | 2 +- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/Constants.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/Constants.java index 66cc1571..212c0b8e 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/Constants.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/Constants.java @@ -19,11 +19,12 @@ public interface Constants { // Images public static final String IMAGE_PATH = "icons/"; public static final String IMAGE_UNKNOWN = "sample.gif"; + public static final String IMAGE_DEFAULT = "editor.gif"; public static final String IMAGE_OPEN = "prompt.gif"; public static final String IMAGE_RUN = "run_exc.gif"; public static final String IMAGE_EXPLORE = "fldr_obj.gif"; public static final String IMAGE_CLIPBOARD = "copy.gif"; - public static final String IMAGE_OTHER = "editor.gif"; + public static final String IMAGE_OTHER = "environment_obj.gif"; // Preferences public static final String PREF_COMMANDS_PRESET = "COMMANDS_PRESET"; @@ -33,6 +34,7 @@ public interface Constants { // Actions public static final String ACTION_UNKNOWN = "de.anbos.eclipse.easyshell.plugin.commands.Unknown"; + public static final String ACTION_DEFAULT = "de.anbos.eclipse.easyshell.plugin.commands.Default"; public static final String ACTION_OPEN = "de.anbos.eclipse.easyshell.plugin.commands.Open"; public static final String ACTION_RUN = "de.anbos.eclipse.easyshell.plugin.commands.Run"; public static final String ACTION_EXPLORE = "de.anbos.eclipse.easyshell.plugin.commands.Explore"; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java index 1ca8c648..d42a23e8 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java @@ -104,6 +104,9 @@ private void addWindowsCommands() { private void addLinuxCommands() { // Linux KDE Konsole + list.add(new CommandData("51ed300a-35d0-4e67-a5f8-6ebd7012a564", PresetType.presetPlugin, OS.osLinux, "XDG Open", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeDefault, + "xdg-open ${easyshell:resource_loc}")); + // Linux KDE Konsole list.add(new CommandData("c2b1612b-9037-484a-a763-d013679bdbe7", PresetType.presetPlugin, OS.osLinux, "KDE Konsole", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, "konsole --workdir ${easyshell:container_loc}")); list.add(new CommandData("e634b20a-cf57-47f0-aa27-b8fc95917f35", PresetType.presetPlugin, OS.osLinux, "KDE Konsole", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/CommandType.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/CommandType.java index 7fd53fc7..0c25be10 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/CommandType.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/CommandType.java @@ -18,11 +18,12 @@ public enum CommandType { commandTypeUnknown(-1, "Unknown", Constants.IMAGE_UNKNOWN, Constants.ACTION_UNKNOWN), - commandTypeOpen(0, "Open", Constants.IMAGE_OPEN, Constants.ACTION_OPEN), - commandTypeRun(1, "Run", Constants.IMAGE_RUN, Constants.ACTION_RUN), - commandTypeExplore(2, "Explore", Constants.IMAGE_EXPLORE, Constants.ACTION_EXPLORE), - commandTypeClipboard(3, "Clipboard", Constants.IMAGE_CLIPBOARD, Constants.ACTION_CLIPBOARD), - commandTypeOther(4, "Other", Constants.IMAGE_OTHER, Constants.ACTION_OTHER); + commandTypeDefault(0, "Default", Constants.IMAGE_DEFAULT, Constants.ACTION_DEFAULT), + commandTypeOpen(1, "Open", Constants.IMAGE_OPEN, Constants.ACTION_OPEN), + commandTypeRun(2, "Run", Constants.IMAGE_RUN, Constants.ACTION_RUN), + commandTypeExplore(3, "Explore", Constants.IMAGE_EXPLORE, Constants.ACTION_EXPLORE), + commandTypeClipboard(4, "Clipboard", Constants.IMAGE_CLIPBOARD, Constants.ACTION_CLIPBOARD), + commandTypeOther(5, "Other", Constants.IMAGE_OTHER, Constants.ACTION_OTHER); // attributes private final int id; private final String name; diff --git a/uuids.txt b/uuids.txt index bacb1857..ddf6457a 100644 --- a/uuids.txt +++ b/uuids.txt @@ -20,6 +20,7 @@ e487327c-dfdb-42e7-bf16-3b81a34e5703 67aa9dff-6bbb-4b47-8b43-8a82a7a279fa Linux +51ed300a-35d0-4e67-a5f8-6ebd7012a564 c2b1612b-9037-484a-a763-d013679bdbe7 e634b20a-cf57-47f0-aa27-b8fc95917f35 8873342e-e02b-4feb-8f56-9f52524c0f46 @@ -43,7 +44,6 @@ f6bcdd71-4687-46d8-bf34-2780bafd762a cd32fa5a-34d7-4551-8bd0-3aae0dc444d0 Free -51ed300a-35d0-4e67-a5f8-6ebd7012a564 8e366a34-5ce2-4430-bc21-20e176e0128c 2a979af5-86a7-440e-b4f0-8442e85412e4 cb9a8c00-89bc-453c-aeff-ae94c0d9e44a From 4866afd697b6e2af04a6416641ffec5ab4a6f83e Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Sun, 24 Jul 2016 18:14:05 +0200 Subject: [PATCH 23/73] #23 add linux 'thunar' file browser - cannot select files only folders --- .../plugin/preferences/CommandDataDefaultCollection.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java index d42a23e8..49cad27f 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java @@ -143,7 +143,7 @@ private void addLinuxCommands() { "nemo ${easyshell:resource_loc}")); // Linux Thunar list.add(new CommandData("cf8d4d60-10f4-4a31-a423-676d02d974e0", PresetType.presetPlugin, OS.osLinux, "Thunar", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, - "thunar ${easyshell:resource_loc}")); + "thunar ${easyshell:container_loc}")); // Linux Clipboard list.add(new CommandData("33043fe3-1a5f-46d7-b94e-9a02ef204e7d", PresetType.presetPlugin, OS.osLinux, "Full path", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeClipboard, "${easyshell:resource_loc}${easyshell:line_separator}")); @@ -192,7 +192,9 @@ private static List getDefaultCommands() { addNotNull(listDefault, getCommandData(listOS, "Explorer", CommandType.commandTypeExplore)); break; case osLinux: - // try to detect the desktop + // add default preset for all desktops (XDG-open) + addNotNull(listDefault, getCommandData(listOS, ".*", CommandType.commandTypeDefault)); + // try to detect the desktop LinuxDesktop desktop = Utils.detectLinuxDesktop(); //Activator.getDefault().sysout(true, "Detected linux (Unix) desktop: >" + desktop.getName() + "<"); switch (desktop) { From ea2e88cd73576833f68a14ce551c785f8a7bf210 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Sun, 24 Jul 2016 18:29:42 +0200 Subject: [PATCH 24/73] #20 add sakura terminal emulator to linux presets Signed-off-by: Andre Bossert --- .../plugin/preferences/CommandDataDefaultCollection.java | 5 +++++ uuids.txt | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java index 49cad27f..5d3d41c9 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java @@ -129,6 +129,11 @@ private void addLinuxCommands() { "pantheon-terminal --working-directory=${easyshell:container_loc}")); list.add(new CommandData("22ec69ee-e39e-4fa6-a241-4e950d3235af", PresetType.presetPlugin, OS.osLinux, "Pantheon Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, "pantheon-terminal --working-directory=${easyshell:container_loc} --execute=./''${easyshell:resource_name}''")); + // Linux Sakura Terminal + list.add(new CommandData("8e366a34-5ce2-4430-bc21-20e176e0128c", PresetType.presetPlugin, OS.osLinux, "Sakura Terminal", ResourceType.resourceTypeFileOrDirectory, true, "${easyshell:container_loc}", CommandType.commandTypeOpen, + "sakura")); + list.add(new CommandData("2a979af5-86a7-440e-b4f0-8442e85412e4", PresetType.presetPlugin, OS.osLinux, "Sakura Terminal", ResourceType.resourceTypeFileOrDirectory, true, "${easyshell:container_loc}", CommandType.commandTypeRun, + "sakura --execute=./''${easyshell:resource_name}'' --hold")); // Linux Pantheon Filebrowser list.add(new CommandData("025e2f56-3d2e-47e1-8daa-c2c74049b150", PresetType.presetPlugin, OS.osLinux, "Pantheon", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, "pantheon-files ${easyshell:resource_loc}")); diff --git a/uuids.txt b/uuids.txt index ddf6457a..ec5f7c03 100644 --- a/uuids.txt +++ b/uuids.txt @@ -28,6 +28,8 @@ e634b20a-cf57-47f0-aa27-b8fc95917f35 c6126958-32f2-4f96-9933-69ddd956f2e9 8175f9a7-4e54-4367-a6b6-251aedc187df adf40e10-0ee9-4abe-8282-aff7d51bb68d +8e366a34-5ce2-4430-bc21-20e176e0128c +2a979af5-86a7-440e-b4f0-8442e85412e4 e5b3b0f6-e27c-4a2d-aa1a-caef784dd3da 22ec69ee-e39e-4fa6-a241-4e950d3235af 025e2f56-3d2e-47e1-8daa-c2c74049b150 @@ -44,8 +46,6 @@ f6bcdd71-4687-46d8-bf34-2780bafd762a cd32fa5a-34d7-4551-8bd0-3aae0dc444d0 Free -8e366a34-5ce2-4430-bc21-20e176e0128c -2a979af5-86a7-440e-b4f0-8442e85412e4 cb9a8c00-89bc-453c-aeff-ae94c0d9e44a f573a4de-22fa-467f-a433-042d0992ab28 1cc39e61-8d8d-4493-8baa-7a11ff01c06c From 9c6f80f7120ab9bd2ab507b620fe3e1a220b91ec Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Sun, 24 Jul 2016 18:53:12 +0200 Subject: [PATCH 25/73] #26 - add linux 'PCManFM' file browser Signed-off-by: Andre Bossert --- .../preferences/CommandDataDefaultCollection.java | 13 ++++++++----- uuids.txt | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java index 5d3d41c9..63441a80 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java @@ -124,19 +124,22 @@ private void addLinuxCommands() { "xfce4-terminal --working-directory=${easyshell:container_loc}")); list.add(new CommandData("adf40e10-0ee9-4abe-8282-aff7d51bb68d", PresetType.presetPlugin, OS.osLinux, "Xfce Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, "xfce4-terminal --working-directory=${easyshell:container_loc} --command=./''${easyshell:resource_name}'' --hold")); - // Linux Pantheon Terminal - list.add(new CommandData("e5b3b0f6-e27c-4a2d-aa1a-caef784dd3da", PresetType.presetPlugin, OS.osLinux, "Pantheon Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, - "pantheon-terminal --working-directory=${easyshell:container_loc}")); - list.add(new CommandData("22ec69ee-e39e-4fa6-a241-4e950d3235af", PresetType.presetPlugin, OS.osLinux, "Pantheon Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, - "pantheon-terminal --working-directory=${easyshell:container_loc} --execute=./''${easyshell:resource_name}''")); // Linux Sakura Terminal list.add(new CommandData("8e366a34-5ce2-4430-bc21-20e176e0128c", PresetType.presetPlugin, OS.osLinux, "Sakura Terminal", ResourceType.resourceTypeFileOrDirectory, true, "${easyshell:container_loc}", CommandType.commandTypeOpen, "sakura")); list.add(new CommandData("2a979af5-86a7-440e-b4f0-8442e85412e4", PresetType.presetPlugin, OS.osLinux, "Sakura Terminal", ResourceType.resourceTypeFileOrDirectory, true, "${easyshell:container_loc}", CommandType.commandTypeRun, "sakura --execute=./''${easyshell:resource_name}'' --hold")); + // Linux Pantheon Terminal + list.add(new CommandData("e5b3b0f6-e27c-4a2d-aa1a-caef784dd3da", PresetType.presetPlugin, OS.osLinux, "Pantheon Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, + "pantheon-terminal --working-directory=${easyshell:container_loc}")); + list.add(new CommandData("22ec69ee-e39e-4fa6-a241-4e950d3235af", PresetType.presetPlugin, OS.osLinux, "Pantheon Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, + "pantheon-terminal --working-directory=${easyshell:container_loc} --execute=./''${easyshell:resource_name}''")); // Linux Pantheon Filebrowser list.add(new CommandData("025e2f56-3d2e-47e1-8daa-c2c74049b150", PresetType.presetPlugin, OS.osLinux, "Pantheon", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, "pantheon-files ${easyshell:resource_loc}")); + // Linux PCManFM + list.add(new CommandData("cb9a8c00-89bc-453c-aeff-ae94c0d9e44a", PresetType.presetPlugin, OS.osLinux, "PCManFM", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, + "pcmanfm ${easyshell:container_loc}")); // Linux Nautilus list.add(new CommandData("1747b189-ed7f-4546-8c98-f99a3c1fb13b", PresetType.presetPlugin, OS.osLinux, "Nautilus", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, "nautilus ${easyshell:resource_loc}")); diff --git a/uuids.txt b/uuids.txt index ec5f7c03..8a83249c 100644 --- a/uuids.txt +++ b/uuids.txt @@ -33,6 +33,7 @@ adf40e10-0ee9-4abe-8282-aff7d51bb68d e5b3b0f6-e27c-4a2d-aa1a-caef784dd3da 22ec69ee-e39e-4fa6-a241-4e950d3235af 025e2f56-3d2e-47e1-8daa-c2c74049b150 +cb9a8c00-89bc-453c-aeff-ae94c0d9e44a 1747b189-ed7f-4546-8c98-f99a3c1fb13b 4fbfa632-5455-4384-9f9e-773603a12bea 8e14d26d-2981-4b81-b8e5-6a942c6f2c59 @@ -46,7 +47,6 @@ f6bcdd71-4687-46d8-bf34-2780bafd762a cd32fa5a-34d7-4551-8bd0-3aae0dc444d0 Free -cb9a8c00-89bc-453c-aeff-ae94c0d9e44a f573a4de-22fa-467f-a433-042d0992ab28 1cc39e61-8d8d-4493-8baa-7a11ff01c06c 88989d78-cf17-4750-91fc-6260055743ae From 947ff408ecb38d51723e18187978d2b962635cd9 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Sun, 24 Jul 2016 19:03:07 +0200 Subject: [PATCH 26/73] #25 add ROXTerm to linux presets Signed-off-by: Andre Bossert --- .../plugin/preferences/CommandDataDefaultCollection.java | 5 +++++ uuids.txt | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java index 63441a80..39f2f13e 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java @@ -129,6 +129,11 @@ private void addLinuxCommands() { "sakura")); list.add(new CommandData("2a979af5-86a7-440e-b4f0-8442e85412e4", PresetType.presetPlugin, OS.osLinux, "Sakura Terminal", ResourceType.resourceTypeFileOrDirectory, true, "${easyshell:container_loc}", CommandType.commandTypeRun, "sakura --execute=./''${easyshell:resource_name}'' --hold")); + // Linux ROXTerm + list.add(new CommandData("f573a4de-22fa-467f-a433-042d0992ab28", PresetType.presetPlugin, OS.osLinux, "ROXTerm", ResourceType.resourceTypeFileOrDirectory, true, "${easyshell:container_loc}", CommandType.commandTypeOpen, + "roxterm --title=${easyshell:project_name} --directory=${easyshell:container_loc}")); + list.add(new CommandData("1cc39e61-8d8d-4493-8baa-7a11ff01c06c", PresetType.presetPlugin, OS.osLinux, "ROXTerm", ResourceType.resourceTypeFileOrDirectory, true, "${easyshell:container_loc}", CommandType.commandTypeRun, + "roxterm --title=${easyshell:project_name} --directory=${easyshell:container_loc} --execute ./''${easyshell:resource_name}''")); // Linux Pantheon Terminal list.add(new CommandData("e5b3b0f6-e27c-4a2d-aa1a-caef784dd3da", PresetType.presetPlugin, OS.osLinux, "Pantheon Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, "pantheon-terminal --working-directory=${easyshell:container_loc}")); diff --git a/uuids.txt b/uuids.txt index 8a83249c..7afc7146 100644 --- a/uuids.txt +++ b/uuids.txt @@ -30,6 +30,8 @@ c6126958-32f2-4f96-9933-69ddd956f2e9 adf40e10-0ee9-4abe-8282-aff7d51bb68d 8e366a34-5ce2-4430-bc21-20e176e0128c 2a979af5-86a7-440e-b4f0-8442e85412e4 +f573a4de-22fa-467f-a433-042d0992ab28 +1cc39e61-8d8d-4493-8baa-7a11ff01c06c e5b3b0f6-e27c-4a2d-aa1a-caef784dd3da 22ec69ee-e39e-4fa6-a241-4e950d3235af 025e2f56-3d2e-47e1-8daa-c2c74049b150 @@ -47,8 +49,6 @@ f6bcdd71-4687-46d8-bf34-2780bafd762a cd32fa5a-34d7-4551-8bd0-3aae0dc444d0 Free -f573a4de-22fa-467f-a433-042d0992ab28 -1cc39e61-8d8d-4493-8baa-7a11ff01c06c 88989d78-cf17-4750-91fc-6260055743ae e6de32cc-342a-46a0-a766-ac74e7e4000d d2726c3f-6da3-46b5-8029-1c63d0ff6bd2 From 53d2ea1e0f4844dd210939a9f614d5b01cd1c51e Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Mon, 25 Jul 2016 13:09:04 +0200 Subject: [PATCH 27/73] fixed checked items refresh in menu-table after filtering Signed-off-by: Andre Bossert --- .../plugin/preferences/CommandPage.java | 4 ++- .../plugin/preferences/MenuPage.java | 30 +++++++++++-------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java index 4ee356d6..22ad6f2b 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java @@ -205,7 +205,9 @@ private void createTableViewer(Composite parent) { tableViewer.setLabelProvider(new CommandDataLabelProvider()); tableViewer.setContentProvider(new CommandDataContentProvider()); - tableViewer.addFilter(filter); + if (filter != null) { + tableViewer.addFilter(filter); + } // Get the content for the viewer, setInput will call getElements in the // contentProvider diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java index 5b86593f..9e9d61cf 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java @@ -107,10 +107,7 @@ protected void performDefaults() { int result = dialog.open(); if (result == 0) { menuStore.loadDefaults(); - tableViewer.refresh(); - for (MenuData item : menuStore.getDataList()) { - tableViewer.setChecked(item, true); - } + refreshTableViewer(); } } @@ -147,10 +144,12 @@ protected Control createContents(Composite parent) { // buttons createButtons(pageComponent); - // send event to refresh tableViewer + // refresh the viewer + refreshTableViewer(); + + // send event to refresh tableViewer selection Event event = new Event(); event.item = null; - tableViewer.refresh(); tableViewer.getTable().notifyListeners(SWT.Selection, event); return pageComponent; @@ -180,7 +179,7 @@ private void createSearchField(Composite parent) { searchText.addKeyListener(new KeyAdapter() { public void keyReleased(KeyEvent ke) { filter.setSearchText(searchText.getText()); - tableViewer.refresh(); + refreshTableViewer(); } }); @@ -223,16 +222,14 @@ private void createTableViewer(Composite parent) { tableViewer.setLabelProvider(new MenuDataLabelProvider()); tableViewer.setContentProvider(new MenuDataContentProvider()); - tableViewer.addFilter(filter); + if (filter != null) { + tableViewer.addFilter(filter); + } // Get the content for the viewer, setInput will call getElements in the // contentProvider tableViewer.setInput(menuStore); - // update/set checked elements - tableViewer.setAllChecked(false); - tableViewer.setCheckedElements(menuStore.getEnabledCommandMenuDataArray()); - // Layout the viewer GridData gridData = new GridData(); gridData.verticalAlignment = GridData.FILL; @@ -457,7 +454,7 @@ private void removeDialog() { MenuData data = (MenuData) elements.next(); menuStore.delete(data); } - tableViewer.refresh(); + refreshTableViewer(); } } @@ -477,4 +474,11 @@ private void refreshTableViewer(MenuData data) { tableViewer.setSelection(new StructuredSelection(data)); } + private void refreshTableViewer() { + tableViewer.refresh(); + // update/set checked elements + tableViewer.setAllChecked(false); + tableViewer.setCheckedElements(menuStore.getEnabledCommandMenuDataArray()); + } + } \ No newline at end of file From 327be2a3bd9e1a0aed47051f7ffd2971be0abc6e Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Mon, 25 Jul 2016 15:18:54 +0200 Subject: [PATCH 28/73] added showing of commands defined by plugin (read only) Signed-off-by: Andre Bossert --- .../easyshell/plugin/UIMessages.properties | 54 ++++++++++--------- .../plugin/preferences/CommandDataDialog.java | 45 +++++++++------- .../preferences/CommandDataLabelProvider.java | 6 ++- .../plugin/preferences/CommandPage.java | 51 ++++++++++-------- .../plugin/preferences/MenuDataDialog.java | 33 ++++++++---- 5 files changed, 112 insertions(+), 77 deletions(-) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties index 9f31a469..75f8a561 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties @@ -19,7 +19,7 @@ easyshell.menu.page.header.title.column1=Command easyshell.menu.page.button.text.new=Add... easyshell.menu.page.button.tooltip.new=Add new menu easyshell.menu.page.button.text.copy=Copy... -easyshell.menu.page.button.tooltip.copy=Copy selected menu as new menu +easyshell.menu.page.button.tooltip.copy=Copy selected menu to new menu easyshell.menu.page.button.text.edit=Edit... easyshell.menu.page.button.tooltip.edit=Edit selected menu easyshell.menu.page.button.text.remove=Remove... @@ -36,16 +36,18 @@ easyshell.menu.page.dialog.defaults.question=All your menu definitions will be o easyshell.menu.page.dialog.migration.title=Migration easyshell.menu.page.dialog.migration.question=You have canceled the migration of settings from previous version.\n\nAll your menu definitions will be written now and migration will be skipped completely!\n\nDo you really want to overwrite the migrated settings? -easyshell.command.page.header.title.column0=Name -easyshell.command.page.header.title.column1=Command +easyshell.command.page.header.title.column0=Category +easyshell.command.page.header.title.column1=Name +easyshell.command.page.header.title.column2=Defined by +easyshell.command.page.header.title.column3=Command easyshell.command.page.text.text.search=Search easyshell.command.page.text.tooltip.search=Enter your search pattern here easyshell.command.page.button.text.new=Add... -easyshell.command.page.button.tooltip.new=Add new menu +easyshell.command.page.button.tooltip.new=Add new command easyshell.command.page.button.text.copy=Copy... -easyshell.command.page.button.tooltip.copy=Copy selected menu as new menu -easyshell.command.page.button.text.edit=Edit... -easyshell.command.page.button.tooltip.edit=Edit selected menu +easyshell.command.page.button.tooltip.copy=Copy selected command to new command +easyshell.command.page.button.text.edit=Show/Edit... +easyshell.command.page.button.tooltip.edit=Show or edit selected command easyshell.command.page.button.text.remove=Remove... easyshell.command.page.button.tooltip.remove=Remove selected commands(s) easyshell.command.page.dialog.remove.title=Remove command(s) @@ -62,26 +64,28 @@ easyshell.menu.editor.dialog.title.group1=Menu definition easyshell.menu.editor.dialog.title.group2=Command definition easyshell.menu.editor.dialog.error.text.name=Please enter a valid name easyshell.menu.editor.dialog.error.type.text=Please choose a valid type -easyshell.menu.editor.dialog.label.active=enabled: -easyshell.menu.editor.dialog.label.name=name: +easyshell.menu.editor.dialog.label.active=Enabled: +easyshell.menu.editor.dialog.label.name=Name: easyshell.menu.editor.dialog.label.pattern= -easyshell.menu.editor.dialog.label.combo.preset=select: -easyshell.menu.editor.dialog.label.combo.pattern=name pattern: -easyshell.menu.editor.dialog.label.command=command: +easyshell.menu.editor.dialog.label.combo.preset=Select: +easyshell.menu.editor.dialog.label.combo.pattern=Pattern: +easyshell.menu.editor.dialog.label.command=Command: easyshell.menu.editor.dialog.button.text.new=New... -easyshell.menu.editor.dialog.button.tooltip.new=Add new user command +easyshell.menu.editor.dialog.button.tooltip.new=Add new command easyshell.menu.editor.dialog.button.text.copy=Copy... -easyshell.menu.editor.dialog.button.tooltip.copy=Copy selected command as user command -easyshell.menu.editor.dialog.button.text.edit=Edit... -easyshell.menu.editor.dialog.button.tooltip.edit=Edit selected user command +easyshell.menu.editor.dialog.button.tooltip.copy=Copy selected command to new command +easyshell.menu.editor.dialog.button.text.edit=Show/Edit... +easyshell.menu.editor.dialog.button.tooltip.edit=Show or edit selected command easyshell.menu.editor.dialog.button.text.remove=Remove... -easyshell.menu.editor.dialog.button.tooltip.remove=Remove selected user command -easyshell.menu.editor.dialog.title.remove=Remove user command -easyshell.menu.editor.dialog.question.remove=Do you really want to remove user command\n"{0}" ? +easyshell.menu.editor.dialog.button.tooltip.remove=Remove selected command +easyshell.menu.editor.dialog.title.remove=Remove command +easyshell.menu.editor.dialog.question.remove=Do you really want to remove command\n"{0}" ? easyshell.command.editor.dialog.title.new=Create new command -easyshell.command.editor.dialog.title.edit=Edit existing command +easyshell.command.editor.dialog.title.copy=Copy to new command +easyshell.command.editor.dialog.title.edit=Edit command (defined by user) +easyshell.command.editor.dialog.title.show=Show command (defined by plugin) easyshell.command.editor.dialog.title.group1=Command easyshell.command.editor.dialog.tooltip.group1=Add your command here easyshell.command.editor.dialog.title.group2=Usable variables @@ -92,10 +96,10 @@ easyshell.command.editor.dialog.error.text.type=Please choose a valid command ty easyshell.command.editor.dialog.error.text.name=Please enter a valid name easyshell.command.editor.dialog.error.text.workingdir=Please enter a valid working directory easyshell.command.editor.dialog.error.text.value=Please enter a valid command -easyshell.command.editor.dialog.label.combo1=type: -easyshell.command.editor.dialog.label.combo2=resource: -easyshell.command.editor.dialog.label.name=name: -easyshell.command.editor.dialog.label.useworkdir=working directory: +easyshell.command.editor.dialog.label.combo1=Category: +easyshell.command.editor.dialog.label.combo2=Resource: +easyshell.command.editor.dialog.label.name=Name: +easyshell.command.editor.dialog.label.useworkdir=Working directory: easyshell.command.editor.dialog.button.tooltip.useworkdir=Set working directory prior command execution?\n\nNeeded for commands that does not support working directory as parameter. easyshell.command.editor.dialog.label.workdir= -easyshell.command.editor.dialog.label.value=command: +easyshell.command.editor.dialog.label.value=Command: diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java index 03b26390..9878112a 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java @@ -11,6 +11,7 @@ package de.anbos.eclipse.easyshell.plugin.preferences; +import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.StatusDialog; import org.eclipse.swt.SWT; @@ -39,7 +40,7 @@ public class CommandDataDialog extends StatusDialog { private CommandData data; - + private boolean edit; private Combo resourceTypeCombo; private Combo commandTypeCombo; private Text nameText; @@ -47,18 +48,19 @@ public class CommandDataDialog extends StatusDialog { private Text dirText; private Text valueText; - public CommandDataDialog(Shell parent, CommandData data, boolean edit) { + @Override + public void create() { + super.create(); + getButton(IDialogConstants.OK_ID).setEnabled(edit); + } + + public CommandDataDialog(Shell parent, CommandData data, String title, boolean edit) { super(parent); this.data = data; + this.edit = edit; // do layout and title setShellStyle(getShellStyle() | SWT.MAX); // set title - String title = null; - if(edit) { - title = Activator.getResourceString("easyshell.command.editor.dialog.title.edit"); - } else { - title = Activator.getResourceString("easyshell.command.editor.dialog.title.new"); - } setTitle(title); } @@ -151,7 +153,7 @@ private void createDirCheckBox(Composite parent) { @Override public void widgetSelected(SelectionEvent e) { //Button button = (Button)e.getSource(); - dirText.setEnabled(dirCheckBox.getSelection()); + dirText.setEditable(dirCheckBox.getSelection()); if (!dirText.getEnabled() && dirText.getText().isEmpty()) { dirText.setText(data.getWorkingDirectory()); } @@ -163,6 +165,7 @@ public void widgetDefaultSelected(SelectionEvent e) { } }); dirCheckBox.setToolTipText(Activator.getResourceString("easyshell.command.editor.dialog.button.tooltip.useworkdir")); + dirCheckBox.setEnabled(edit); } private void createVariableLabel(Composite parent, String varText, String labelText) { @@ -172,19 +175,16 @@ private void createVariableLabel(Composite parent, String varText, String labelT styledTextWidget.setEditable(false); styledTextWidget.setCaret(null); //Set caret null this will hide caret styledTextWidget.addMouseListener(new MouseListener() { - @Override public void mouseUp(MouseEvent e) { // TODO Auto-generated method stub } - @Override public void mouseDown(MouseEvent e) { // TODO Auto-generated method stub } - @Override public void mouseDoubleClick(MouseEvent e) { StyledText text = (StyledText)(e.getSource()); @@ -223,15 +223,17 @@ private void refreshDirCheckBox() { } protected void okPressed() { - if (!validateValues()) { - return; + if (edit) { + if (!validateValues()) { + return; + } + data.setResourceType(ResourceType.getFromName(resourceTypeCombo.getText())); + data.setCommandType(CommandType.getFromName(commandTypeCombo.getText())); + data.setName(nameText.getText()); + data.setUseWorkingDirectory(dirCheckBox.getSelection()); + data.setWorkingDirectory(dirText.getText()); + data.setCommand(valueText.getText()); } - data.setResourceType(ResourceType.getFromName(resourceTypeCombo.getText())); - data.setCommandType(CommandType.getFromName(commandTypeCombo.getText())); - data.setName(nameText.getText()); - data.setUseWorkingDirectory(dirCheckBox.getSelection()); - data.setWorkingDirectory(dirText.getText()); - data.setCommand(valueText.getText()); super.okPressed(); } @@ -309,6 +311,7 @@ public void widgetDefaultSelected(SelectionEvent e) { return; } } + resourceTypeCombo.setEnabled(edit); } private void createCommandTypeCombo(Composite parent) { @@ -338,6 +341,7 @@ public void widgetDefaultSelected(SelectionEvent e) { return; } } + commandTypeCombo.setEnabled(edit); } private Text createTextField(Composite parent, String labelText, String editValue, boolean emptyLabel) { @@ -352,6 +356,7 @@ private Text createTextField(Composite parent, String labelText, String editValu Text text = new Text(parent,SWT.BORDER); text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); text.setText(editValue); + text.setEditable(edit); return text; } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataLabelProvider.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataLabelProvider.java index 19eb2ad2..f661d46e 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataLabelProvider.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataLabelProvider.java @@ -39,8 +39,12 @@ public String getColumnText(Object element, int columnIndex) { CommandData data = (CommandData)element; switch(columnIndex) { case 0: - return data.getName(); + return data.getCommandType().getName(); case 1: + return data.getName(); + case 2: + return data.getPresetType().getName(); + case 3: return data.getCommand(); default: return ""; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java index 22ad6f2b..94f2d0b8 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java @@ -244,7 +244,7 @@ public void selectionChanged(SelectionChangedEvent event) { } } addCopyButton.setEnabled(selected); - editButton.setEnabled(selected && !presetSelected); + editButton.setEnabled(selected); removeButton.setEnabled(selected && !presetSelected); } }); @@ -274,21 +274,23 @@ public boolean isSorterProperty(Object element, String property) { } private void createColumns(final Composite parent, final TableViewer viewer) { - TableViewerColumn viewerColumn1 = new TableViewerColumn(viewer, - SWT.NONE); - TableColumn column1 = viewerColumn1.getColumn(); - column1.setText(Activator.getResourceString("easyshell.command.page.header.title.column0")); - column1.setWidth(200); - column1.setResizable(true); - column1.setMoveable(true); - - TableViewerColumn viewerColumn2 = new TableViewerColumn(viewer, - SWT.NONE); - TableColumn column2 = viewerColumn2.getColumn(); - column2.setText(Activator.getResourceString("easyshell.command.page.header.title.column1")); - column2.setWidth(400); - column2.setResizable(true); - column2.setMoveable(true); + String[] titles = { + Activator.getResourceString("easyshell.command.page.header.title.column0"), + Activator.getResourceString("easyshell.command.page.header.title.column1"), + Activator.getResourceString("easyshell.command.page.header.title.column2"), + Activator.getResourceString("easyshell.command.page.header.title.column3") + }; + int[] bounds = { 100, 100, 80, 400 }; + // create + for (int i=0;i Date: Mon, 25 Jul 2016 15:32:35 +0200 Subject: [PATCH 29/73] fixed windows command names and searching Signed-off-by: Andre Bossert --- plugin/plugin.xml | 4 ++-- .../plugin/preferences/CommandDataDefaultCollection.java | 6 +++--- .../easyshell/plugin/preferences/CommandTableFilter.java | 6 ++++++ 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/plugin/plugin.xml b/plugin/plugin.xml index 3e45ff0b..e59efa93 100644 --- a/plugin/plugin.xml +++ b/plugin/plugin.xml @@ -68,7 +68,7 @@ category="de.anbos.eclipse.easyshell.plugin.preferences.MainPage" class="de.anbos.eclipse.easyshell.plugin.preferences.MenuPage" id="de.anbos.eclipse.easyshell.plugin.preferences.MenuPage" - name="Menu"> + name="(1) Menu"> + name="(2) Command"> Date: Mon, 25 Jul 2016 20:57:08 +0200 Subject: [PATCH 30/73] #60 [v2.0] rename the "type" option to "category" - added Category - reduced CommandType to Execute and Clipboard - adapted reading of older stores Signed-off-by: Andre Bossert --- .../eclipse/easyshell/plugin/Activator.java | 4 +- .../eclipse/easyshell/plugin/Constants.java | 6 +- .../easyshell/plugin/UIMessages.properties | 6 +- .../plugin/commands/DefineCommands.java | 2 +- .../plugin/preferences/CommandData.java | 26 +++- .../CommandDataDefaultCollection.java | 131 +++++++++--------- .../plugin/preferences/CommandDataDialog.java | 63 ++++++++- .../preferences/CommandDataLabelProvider.java | 4 +- .../plugin/preferences/CommandPage.java | 3 +- .../preferences/CommandTableFilter.java | 2 +- .../plugin/preferences/MenuData.java | 14 +- .../plugin/preferences/MenuDataDialog.java | 5 +- .../preferences/MenuDataLabelProvider.java | 2 +- .../easyshell/plugin/types/Category.java | 114 +++++++++++++++ .../easyshell/plugin/types/CommandType.java | 44 +++--- .../easyshell/plugin/types/MenuNameType.java | 6 +- 16 files changed, 312 insertions(+), 120 deletions(-) create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/types/Category.java diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java index 3a228170..ebc9855a 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java @@ -31,7 +31,7 @@ import org.osgi.framework.BundleContext; -import de.anbos.eclipse.easyshell.plugin.types.CommandType; +import de.anbos.eclipse.easyshell.plugin.types.Category; import de.anbos.eclipse.easyshell.plugin.types.Debug; import de.anbos.eclipse.easyshell.plugin.types.Version; @@ -109,7 +109,7 @@ public static ImageDescriptor getImageDescriptor(String id) { protected void initializeImageRegistry(ImageRegistry registry) { Bundle bundle = Platform.getBundle(Constants.PLUGIN_ID); - for (String icon : CommandType.getIconsAsList()) { + for (String icon : Category.getIconsAsList()) { addImageToRegistry(registry, bundle, Constants.IMAGE_PATH + icon, icon); } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/Constants.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/Constants.java index 212c0b8e..54c8c06a 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/Constants.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/Constants.java @@ -34,10 +34,6 @@ public interface Constants { // Actions public static final String ACTION_UNKNOWN = "de.anbos.eclipse.easyshell.plugin.commands.Unknown"; - public static final String ACTION_DEFAULT = "de.anbos.eclipse.easyshell.plugin.commands.Default"; - public static final String ACTION_OPEN = "de.anbos.eclipse.easyshell.plugin.commands.Open"; - public static final String ACTION_RUN = "de.anbos.eclipse.easyshell.plugin.commands.Run"; - public static final String ACTION_EXPLORE = "de.anbos.eclipse.easyshell.plugin.commands.Explore"; + public static final String ACTION_EXECUTE = "de.anbos.eclipse.easyshell.plugin.commands.Execute"; public static final String ACTION_CLIPBOARD = "de.anbos.eclipse.easyshell.plugin.commands.Clipboard"; - public static final String ACTION_OTHER = "de.anbos.eclipse.easyshell.plugin.commands.Other"; } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties index 75f8a561..ab203109 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties @@ -92,12 +92,14 @@ easyshell.command.editor.dialog.title.group2=Usable variables easyshell.command.editor.dialog.tooltip.group2=Double click at variable copies it to clipboard easyshell.command.editor.dialog.error.title.incompletedata=Missing or wrong parameters easyshell.command.editor.dialog.error.text.resource=Please choose a valid resource type +easyshell.command.editor.dialog.error.text.category=Please choose a valid category easyshell.command.editor.dialog.error.text.type=Please choose a valid command type easyshell.command.editor.dialog.error.text.name=Please enter a valid name easyshell.command.editor.dialog.error.text.workingdir=Please enter a valid working directory easyshell.command.editor.dialog.error.text.value=Please enter a valid command -easyshell.command.editor.dialog.label.combo1=Category: -easyshell.command.editor.dialog.label.combo2=Resource: +easyshell.command.editor.dialog.label.combo.category=Category: +easyshell.command.editor.dialog.label.combo.type=Type: +easyshell.command.editor.dialog.label.combo.resource=Resource: easyshell.command.editor.dialog.label.name=Name: easyshell.command.editor.dialog.label.useworkdir=Working directory: easyshell.command.editor.dialog.button.tooltip.useworkdir=Set working directory prior command execution?\n\nNeeded for commands that does not support working directory as parameter. diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java index 2bf0bede..e4ba2769 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java @@ -49,7 +49,7 @@ public void createContributionItems(IServiceLocator serviceLocator, item.getCommandData().getCommand(), "de.anbos.eclipse.easyshell.plugin.commands.parameter.workingdir", item.getCommandData().isUseWorkingDirectory() ? item.getCommandData().getWorkingDirectory() : "", - item.getCommandData().getCommandType().getIcon()); + item.getCommandData().getCategory().getIcon()); } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java index a59a1849..a0794277 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java @@ -14,6 +14,7 @@ import java.util.StringTokenizer; import java.util.UUID; +import de.anbos.eclipse.easyshell.plugin.types.Category; import de.anbos.eclipse.easyshell.plugin.types.CommandType; import de.anbos.eclipse.easyshell.plugin.types.OS; import de.anbos.eclipse.easyshell.plugin.types.PresetType; @@ -29,10 +30,11 @@ public class CommandData extends Data { private ResourceType resourceType = ResourceType.resourceTypeUnknown; private boolean useWorkingDirectory = false; private String workingDirectory = ""; + private Category category = Category.categoryUnknown; private CommandType commandType = CommandType.commandTypeUnknown; private String command = ""; - public CommandData(String id, PresetType presetType, OS os, String name, ResourceType resType, boolean useWorkingDirectory, String workingDirectory, CommandType cmdType, String command) { + public CommandData(String id, PresetType presetType, OS os, String name, ResourceType resType, boolean useWorkingDirectory, String workingDirectory, Category category, CommandType cmdType, String command) { super(id); this.presetType = presetType; this.os = os; @@ -40,16 +42,17 @@ public CommandData(String id, PresetType presetType, OS os, String name, Resourc this.resourceType = resType; this.useWorkingDirectory = useWorkingDirectory; this.workingDirectory = workingDirectory; + this.category = category; this.commandType = cmdType; this.command = command; } - public CommandData(String id, PresetType presetType, OS os, String name, ResourceType resType, CommandType cmdType, String command) { - this(id, presetType, os, name, resType, false, "${easyshell:container_loc}", cmdType, command); + public CommandData(String id, PresetType presetType, OS os, String name, ResourceType resType, Category category, CommandType cmdType, String command) { + this(id, presetType, os, name, resType, false, "${easyshell:container_loc}", category, cmdType, command); } public CommandData(CommandData commandData, String newId) { - this(newId, commandData.getPresetType(), commandData.getOs(), commandData.getName(), commandData.getResourceType(), commandData.isUseWorkingDirectory(), commandData.getWorkingDirectory(), commandData.getCommandType(), commandData.getCommand()); + this(newId, commandData.getPresetType(), commandData.getOs(), commandData.getName(), commandData.getResourceType(), commandData.isUseWorkingDirectory(), commandData.getWorkingDirectory(), commandData.getCategory(), commandData.getCommandType(), commandData.getCommand()); } public CommandData(CommandData commandData, boolean generateNewId) { @@ -83,6 +86,10 @@ public String getWorkingDirectory() { return workingDirectory; } + public Category getCategory() { + return category; + } + public CommandType getCommandType() { return commandType; } @@ -115,6 +122,10 @@ public void setWorkingDirectory(String workingDirectory) { this.workingDirectory = workingDirectory; } + public void setCategory(Category category) { + this.category = category; + } + public void setCommandType(CommandType cmdType) { this.commandType = cmdType; } @@ -162,12 +173,16 @@ public boolean deserialize(Version version, String value, StringTokenizer tokeni if (version.getId() >= Version.v2_0_003.getId()) { setUseWorkingDirectory(Boolean.valueOf(tokenizer.nextToken()).booleanValue()); setWorkingDirectory(tokenizer.nextToken()); + setCategory(Category.getFromEnum(tokenizer.nextToken())); + setCommandType(CommandType.getFromEnum(tokenizer.nextToken())); } else { setUseWorkingDirectory(false); setWorkingDirectory("${easyshell:container_loc}"); + String commandTypeStr = tokenizer.nextToken(); + setCategory(Category.getFromDeprecatedCommandTypeEnum(commandTypeStr)); + setCommandType(CommandType.getFromDeprecatedCommandTypeEnum(commandTypeStr)); } // go on compatible - setCommandType(CommandType.getFromEnum(tokenizer.nextToken())); setCommand(tokenizer.nextToken()); return true; } @@ -186,6 +201,7 @@ public String serialize(Version version, String delimiter) { if (version.getId() >= Version.v2_0_003.getId()) { ret += Boolean.toString(isUseWorkingDirectory()) + delimiter; ret += getWorkingDirectory() + delimiter; + ret += getCategory().toString() + delimiter; } ret += getCommandType().toString() + delimiter; ret += getCommand() + delimiter; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java index be214bba..5cb173bd 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java @@ -18,6 +18,7 @@ import de.anbos.eclipse.easyshell.plugin.Activator; import de.anbos.eclipse.easyshell.plugin.Utils; +import de.anbos.eclipse.easyshell.plugin.types.Category; import de.anbos.eclipse.easyshell.plugin.types.CommandType; import de.anbos.eclipse.easyshell.plugin.types.LinuxDesktop; import de.anbos.eclipse.easyshell.plugin.types.OS; @@ -62,117 +63,117 @@ public static List getCommandsNativeAsMenu(boolean sorted) { private void addWindowsCommands() { // Windows DOS-Shell - list.add(new CommandData("cd361a40-bb37-4fa2-9d2e-b62794294a59", PresetType.presetPlugin, OS.osWindows, "DOS-Shell", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, + list.add(new CommandData("cd361a40-bb37-4fa2-9d2e-b62794294a59", PresetType.presetPlugin, OS.osWindows, "DOS-Shell", ResourceType.resourceTypeFileOrDirectory, Category.categoryOpen, CommandType.commandTypeExecute, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} cmd.exe /K")); - list.add(new CommandData("f740984b-e9d5-4ebc-b9b5-c6b8527f886c", PresetType.presetPlugin, OS.osWindows, "DOS-Shell", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, + list.add(new CommandData("f740984b-e9d5-4ebc-b9b5-c6b8527f886c", PresetType.presetPlugin, OS.osWindows, "DOS-Shell", ResourceType.resourceTypeFileOrDirectory, Category.categoryRun, CommandType.commandTypeExecute, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} ${easyshell:resource_name}")); // Windows Explorer - list.add(new CommandData("ae0e5b6e-0b20-4c52-9708-ba7e317d1dee", PresetType.presetPlugin, OS.osWindows, "Explorer", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, + list.add(new CommandData("ae0e5b6e-0b20-4c52-9708-ba7e317d1dee", PresetType.presetPlugin, OS.osWindows, "Explorer", ResourceType.resourceTypeFileOrDirectory, Category.categoryExplore, CommandType.commandTypeExecute, "explorer.exe /select, ${easyshell:resource_loc}")); // Windows PowerShell - list.add(new CommandData("9cb0d29e-93aa-4139-93d2-079ba63ff726", PresetType.presetPlugin, OS.osWindows, "PowerShell", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, + list.add(new CommandData("9cb0d29e-93aa-4139-93d2-079ba63ff726", PresetType.presetPlugin, OS.osWindows, "PowerShell", ResourceType.resourceTypeFileOrDirectory, Category.categoryOpen, CommandType.commandTypeExecute, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} powershell.exe")); - list.add(new CommandData("af2968d0-3a1a-40db-b3cb-e2e16293a285", PresetType.presetPlugin, OS.osWindows, "PowerShell", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, + list.add(new CommandData("af2968d0-3a1a-40db-b3cb-e2e16293a285", PresetType.presetPlugin, OS.osWindows, "PowerShell", ResourceType.resourceTypeFileOrDirectory, Category.categoryRun, CommandType.commandTypeExecute, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} powershell.exe -command ./''${easyshell:resource_name}''")); // Windows Cygwin (Bash) - list.add(new CommandData("5b1e3806-a9ab-4866-b660-823ac388a575", PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, + list.add(new CommandData("5b1e3806-a9ab-4866-b660-823ac388a575", PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceTypeFileOrDirectory, Category.categoryOpen, CommandType.commandTypeExecute, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Cygwin\\bin\\bash.exe\"")); - list.add(new CommandData("2002e587-70a3-4204-b1a5-6faf6271ad08", PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, + list.add(new CommandData("2002e587-70a3-4204-b1a5-6faf6271ad08", PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceTypeFileOrDirectory, Category.categoryRun, CommandType.commandTypeExecute, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Cygwin\\bin\\bash.exe\" -c ./''${easyshell:resource_name}''")); // Windows Console - list.add(new CommandData("60fd43d2-d837-41d1-aaa3-3f5cab6bf0fb", PresetType.presetPlugin, OS.osWindows, "Console", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, + list.add(new CommandData("60fd43d2-d837-41d1-aaa3-3f5cab6bf0fb", PresetType.presetPlugin, OS.osWindows, "Console", ResourceType.resourceTypeFileOrDirectory, Category.categoryOpen, CommandType.commandTypeExecute, "console.exe -w \"${easyshell:project_name}\" -d ${easyshell:container_loc}")); - list.add(new CommandData("af6d97f2-f0a8-46e2-8234-74c0ee3e6007", PresetType.presetPlugin, OS.osWindows, "Console", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, + list.add(new CommandData("af6d97f2-f0a8-46e2-8234-74c0ee3e6007", PresetType.presetPlugin, OS.osWindows, "Console", ResourceType.resourceTypeFileOrDirectory, Category.categoryRun, CommandType.commandTypeExecute, "console.exe -w \"${easyshell:project_name}\" -d ${easyshell:container_loc} -r \"/k\\\"${easyshell:resource_name}\\\"\"")); // Windows Git-Bash - list.add(new CommandData("24419204-c8e5-4d79-a7b8-b14e93077cf0", PresetType.presetPlugin, OS.osWindows, "Git-Bash", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, + list.add(new CommandData("24419204-c8e5-4d79-a7b8-b14e93077cf0", PresetType.presetPlugin, OS.osWindows, "Git-Bash", ResourceType.resourceTypeFileOrDirectory, Category.categoryOpen, CommandType.commandTypeExecute, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Program Files (x86)\\Git\\bin\\bash.exe\" --login -i")); - list.add(new CommandData("ee790c7f-9c6d-40f9-84f6-51a948a59d45", PresetType.presetPlugin, OS.osWindows, "Git-Bash", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, + list.add(new CommandData("ee790c7f-9c6d-40f9-84f6-51a948a59d45", PresetType.presetPlugin, OS.osWindows, "Git-Bash", ResourceType.resourceTypeFileOrDirectory, Category.categoryRun, CommandType.commandTypeExecute, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Program Files (x86)\\Git\\bin\\bash.exe\" --login -i -c ./''${easyshell:resource_name}''")); // Windows ConEmu - list.add(new CommandData("1bd62e22-cd93-4136-b643-1cbb9579c195", PresetType.presetPlugin, OS.osWindows, "ConEmu", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, + list.add(new CommandData("1bd62e22-cd93-4136-b643-1cbb9579c195", PresetType.presetPlugin, OS.osWindows, "ConEmu", ResourceType.resourceTypeFileOrDirectory, Category.categoryOpen, CommandType.commandTypeExecute, "ConEmu.exe /Title \"${easyshell:project_name}\" /Dir \"${easyshell:container_loc}\" /Single /cmd cmd")); - list.add(new CommandData("c2b73077-ffd9-4fb7-9793-189be9f13ebb", PresetType.presetPlugin, OS.osWindows, "ConEmu", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, + list.add(new CommandData("c2b73077-ffd9-4fb7-9793-189be9f13ebb", PresetType.presetPlugin, OS.osWindows, "ConEmu", ResourceType.resourceTypeFileOrDirectory, Category.categoryRun, CommandType.commandTypeExecute, "ConEmu.exe /Title \"${easyshell:project_name}\" /Dir \"${easyshell:container_loc}\" /Single /cmd \"${easyshell:resource_name}\"")); // Windows TotalCommander - list.add(new CommandData("e487327c-dfdb-42e7-bf16-3b81a34e5703", PresetType.presetPlugin, OS.osWindows, "TotalCommander", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, + list.add(new CommandData("e487327c-dfdb-42e7-bf16-3b81a34e5703", PresetType.presetPlugin, OS.osWindows, "TotalCommander", ResourceType.resourceTypeFileOrDirectory, Category.categoryExplore, CommandType.commandTypeExecute, "totalcmd.exe /O /T ${easyshell:container_loc}")); // Windows Clipboard - list.add(new CommandData("67aa9dff-6bbb-4b47-8b43-8a82a7a279fa", PresetType.presetPlugin, OS.osWindows, "Full path", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeClipboard, + list.add(new CommandData("67aa9dff-6bbb-4b47-8b43-8a82a7a279fa", PresetType.presetPlugin, OS.osWindows, "Full path", ResourceType.resourceTypeFileOrDirectory, Category.categoryClipboard, CommandType.commandTypeClipboard, "\"${easyshell:resource_loc}\"${easyshell:line_separator}")); } private void addLinuxCommands() { // Linux KDE Konsole - list.add(new CommandData("51ed300a-35d0-4e67-a5f8-6ebd7012a564", PresetType.presetPlugin, OS.osLinux, "XDG Open", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeDefault, + list.add(new CommandData("51ed300a-35d0-4e67-a5f8-6ebd7012a564", PresetType.presetPlugin, OS.osLinux, "XDG Open", ResourceType.resourceTypeFileOrDirectory, Category.categoryDefault, CommandType.commandTypeExecute, "xdg-open ${easyshell:resource_loc}")); // Linux KDE Konsole - list.add(new CommandData("c2b1612b-9037-484a-a763-d013679bdbe7", PresetType.presetPlugin, OS.osLinux, "KDE Konsole", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, + list.add(new CommandData("c2b1612b-9037-484a-a763-d013679bdbe7", PresetType.presetPlugin, OS.osLinux, "KDE Konsole", ResourceType.resourceTypeFileOrDirectory, Category.categoryOpen, CommandType.commandTypeExecute, "konsole --workdir ${easyshell:container_loc}")); - list.add(new CommandData("e634b20a-cf57-47f0-aa27-b8fc95917f35", PresetType.presetPlugin, OS.osLinux, "KDE Konsole", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, + list.add(new CommandData("e634b20a-cf57-47f0-aa27-b8fc95917f35", PresetType.presetPlugin, OS.osLinux, "KDE Konsole", ResourceType.resourceTypeFileOrDirectory, Category.categoryRun, CommandType.commandTypeExecute, "konsole --workdir ${easyshell:container_loc} --noclose -e ${easyshell:resource_loc}")); // Linux Konqueror - list.add(new CommandData("8873342e-e02b-4feb-8f56-9f52524c0f46", PresetType.presetPlugin, OS.osLinux, "Konqueror", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, + list.add(new CommandData("8873342e-e02b-4feb-8f56-9f52524c0f46", PresetType.presetPlugin, OS.osLinux, "Konqueror", ResourceType.resourceTypeFileOrDirectory, Category.categoryExplore, CommandType.commandTypeExecute, "konqueror file:\"${easyshell:resource_loc}\"")); // Linux Gnome Terminal - list.add(new CommandData("53f7b6a3-f8d5-4682-b0ef-1d6ceec5cc8a", PresetType.presetPlugin, OS.osLinux, "Gnome Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, + list.add(new CommandData("53f7b6a3-f8d5-4682-b0ef-1d6ceec5cc8a", PresetType.presetPlugin, OS.osLinux, "Gnome Terminal", ResourceType.resourceTypeFileOrDirectory, Category.categoryOpen, CommandType.commandTypeExecute, "gnome-terminal --working-directory=${easyshell:container_loc}")); - list.add(new CommandData("c6126958-32f2-4f96-9933-69ddd956f2e9", PresetType.presetPlugin, OS.osLinux, "Gnome Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, + list.add(new CommandData("c6126958-32f2-4f96-9933-69ddd956f2e9", PresetType.presetPlugin, OS.osLinux, "Gnome Terminal", ResourceType.resourceTypeFileOrDirectory, Category.categoryRun, CommandType.commandTypeExecute, "gnome-terminal --working-directory=${easyshell:container_loc} --command=./''${easyshell:resource_name}''")); // Linux Xfce Terminal - list.add(new CommandData("8175f9a7-4e54-4367-a6b6-251aedc187df", PresetType.presetPlugin, OS.osLinux, "Xfce Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, + list.add(new CommandData("8175f9a7-4e54-4367-a6b6-251aedc187df", PresetType.presetPlugin, OS.osLinux, "Xfce Terminal", ResourceType.resourceTypeFileOrDirectory, Category.categoryOpen, CommandType.commandTypeExecute, "xfce4-terminal --working-directory=${easyshell:container_loc}")); - list.add(new CommandData("adf40e10-0ee9-4abe-8282-aff7d51bb68d", PresetType.presetPlugin, OS.osLinux, "Xfce Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, + list.add(new CommandData("adf40e10-0ee9-4abe-8282-aff7d51bb68d", PresetType.presetPlugin, OS.osLinux, "Xfce Terminal", ResourceType.resourceTypeFileOrDirectory, Category.categoryRun, CommandType.commandTypeExecute, "xfce4-terminal --working-directory=${easyshell:container_loc} --command=./''${easyshell:resource_name}'' --hold")); // Linux Sakura Terminal - list.add(new CommandData("8e366a34-5ce2-4430-bc21-20e176e0128c", PresetType.presetPlugin, OS.osLinux, "Sakura Terminal", ResourceType.resourceTypeFileOrDirectory, true, "${easyshell:container_loc}", CommandType.commandTypeOpen, + list.add(new CommandData("8e366a34-5ce2-4430-bc21-20e176e0128c", PresetType.presetPlugin, OS.osLinux, "Sakura Terminal", ResourceType.resourceTypeFileOrDirectory, true, "${easyshell:container_loc}", Category.categoryOpen, CommandType.commandTypeExecute, "sakura")); - list.add(new CommandData("2a979af5-86a7-440e-b4f0-8442e85412e4", PresetType.presetPlugin, OS.osLinux, "Sakura Terminal", ResourceType.resourceTypeFileOrDirectory, true, "${easyshell:container_loc}", CommandType.commandTypeRun, + list.add(new CommandData("2a979af5-86a7-440e-b4f0-8442e85412e4", PresetType.presetPlugin, OS.osLinux, "Sakura Terminal", ResourceType.resourceTypeFileOrDirectory, true, "${easyshell:container_loc}", Category.categoryRun, CommandType.commandTypeExecute, "sakura --execute=./''${easyshell:resource_name}'' --hold")); // Linux ROXTerm - list.add(new CommandData("f573a4de-22fa-467f-a433-042d0992ab28", PresetType.presetPlugin, OS.osLinux, "ROXTerm", ResourceType.resourceTypeFileOrDirectory, true, "${easyshell:container_loc}", CommandType.commandTypeOpen, + list.add(new CommandData("f573a4de-22fa-467f-a433-042d0992ab28", PresetType.presetPlugin, OS.osLinux, "ROXTerm", ResourceType.resourceTypeFileOrDirectory, true, "${easyshell:container_loc}", Category.categoryOpen, CommandType.commandTypeExecute, "roxterm --title=${easyshell:project_name} --directory=${easyshell:container_loc}")); - list.add(new CommandData("1cc39e61-8d8d-4493-8baa-7a11ff01c06c", PresetType.presetPlugin, OS.osLinux, "ROXTerm", ResourceType.resourceTypeFileOrDirectory, true, "${easyshell:container_loc}", CommandType.commandTypeRun, + list.add(new CommandData("1cc39e61-8d8d-4493-8baa-7a11ff01c06c", PresetType.presetPlugin, OS.osLinux, "ROXTerm", ResourceType.resourceTypeFileOrDirectory, true, "${easyshell:container_loc}", Category.categoryRun, CommandType.commandTypeExecute, "roxterm --title=${easyshell:project_name} --directory=${easyshell:container_loc} --execute ./''${easyshell:resource_name}''")); // Linux Pantheon Terminal - list.add(new CommandData("e5b3b0f6-e27c-4a2d-aa1a-caef784dd3da", PresetType.presetPlugin, OS.osLinux, "Pantheon Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, + list.add(new CommandData("e5b3b0f6-e27c-4a2d-aa1a-caef784dd3da", PresetType.presetPlugin, OS.osLinux, "Pantheon Terminal", ResourceType.resourceTypeFileOrDirectory, Category.categoryOpen, CommandType.commandTypeExecute, "pantheon-terminal --working-directory=${easyshell:container_loc}")); - list.add(new CommandData("22ec69ee-e39e-4fa6-a241-4e950d3235af", PresetType.presetPlugin, OS.osLinux, "Pantheon Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, + list.add(new CommandData("22ec69ee-e39e-4fa6-a241-4e950d3235af", PresetType.presetPlugin, OS.osLinux, "Pantheon Terminal", ResourceType.resourceTypeFileOrDirectory, Category.categoryRun, CommandType.commandTypeExecute, "pantheon-terminal --working-directory=${easyshell:container_loc} --execute=./''${easyshell:resource_name}''")); // Linux Pantheon Filebrowser - list.add(new CommandData("025e2f56-3d2e-47e1-8daa-c2c74049b150", PresetType.presetPlugin, OS.osLinux, "Pantheon", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, + list.add(new CommandData("025e2f56-3d2e-47e1-8daa-c2c74049b150", PresetType.presetPlugin, OS.osLinux, "Pantheon", ResourceType.resourceTypeFileOrDirectory, Category.categoryExplore, CommandType.commandTypeExecute, "pantheon-files ${easyshell:resource_loc}")); // Linux PCManFM - list.add(new CommandData("cb9a8c00-89bc-453c-aeff-ae94c0d9e44a", PresetType.presetPlugin, OS.osLinux, "PCManFM", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, + list.add(new CommandData("cb9a8c00-89bc-453c-aeff-ae94c0d9e44a", PresetType.presetPlugin, OS.osLinux, "PCManFM", ResourceType.resourceTypeFileOrDirectory, Category.categoryExplore, CommandType.commandTypeExecute, "pcmanfm ${easyshell:container_loc}")); // Linux Nautilus - list.add(new CommandData("1747b189-ed7f-4546-8c98-f99a3c1fb13b", PresetType.presetPlugin, OS.osLinux, "Nautilus", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, + list.add(new CommandData("1747b189-ed7f-4546-8c98-f99a3c1fb13b", PresetType.presetPlugin, OS.osLinux, "Nautilus", ResourceType.resourceTypeFileOrDirectory, Category.categoryExplore, CommandType.commandTypeExecute, "nautilus ${easyshell:resource_loc}")); // Linux Dolphin - list.add(new CommandData("4fbfa632-5455-4384-9f9e-773603a12bea", PresetType.presetPlugin, OS.osLinux, "Dolphin", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, + list.add(new CommandData("4fbfa632-5455-4384-9f9e-773603a12bea", PresetType.presetPlugin, OS.osLinux, "Dolphin", ResourceType.resourceTypeFileOrDirectory, Category.categoryExplore, CommandType.commandTypeExecute, "dolphin --select ${easyshell:resource_loc}")); // Linux Nemo - list.add(new CommandData("8e14d26d-2981-4b81-b8e5-6a942c6f2c59", PresetType.presetPlugin, OS.osLinux, "Nemo", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, + list.add(new CommandData("8e14d26d-2981-4b81-b8e5-6a942c6f2c59", PresetType.presetPlugin, OS.osLinux, "Nemo", ResourceType.resourceTypeFileOrDirectory, Category.categoryExplore, CommandType.commandTypeExecute, "nemo ${easyshell:resource_loc}")); // Linux Thunar - list.add(new CommandData("cf8d4d60-10f4-4a31-a423-676d02d974e0", PresetType.presetPlugin, OS.osLinux, "Thunar", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, + list.add(new CommandData("cf8d4d60-10f4-4a31-a423-676d02d974e0", PresetType.presetPlugin, OS.osLinux, "Thunar", ResourceType.resourceTypeFileOrDirectory, Category.categoryExplore, CommandType.commandTypeExecute, "thunar ${easyshell:container_loc}")); // Linux Clipboard - list.add(new CommandData("33043fe3-1a5f-46d7-b94e-9a02ef204e7d", PresetType.presetPlugin, OS.osLinux, "Full path", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeClipboard, + list.add(new CommandData("33043fe3-1a5f-46d7-b94e-9a02ef204e7d", PresetType.presetPlugin, OS.osLinux, "Full path", ResourceType.resourceTypeFileOrDirectory, Category.categoryClipboard, CommandType.commandTypeClipboard, "${easyshell:resource_loc}${easyshell:line_separator}")); } private void addMacOSXCommands() { // MAC OS X Terminal - list.add(new CommandData("e6918fe0-38b8-450b-a4be-d9eecc0dc0b4", PresetType.presetPlugin, OS.osMacOSX, "Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOpen, + list.add(new CommandData("e6918fe0-38b8-450b-a4be-d9eecc0dc0b4", PresetType.presetPlugin, OS.osMacOSX, "Terminal", ResourceType.resourceTypeFileOrDirectory, Category.categoryOpen, CommandType.commandTypeExecute, "open -a Terminal ${easyshell:container_loc}")); - list.add(new CommandData("db61d61e-8bf4-41d0-a1d8-00379e4d1db1", PresetType.presetPlugin, OS.osMacOSX, "Terminal", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeRun, + list.add(new CommandData("db61d61e-8bf4-41d0-a1d8-00379e4d1db1", PresetType.presetPlugin, OS.osMacOSX, "Terminal", ResourceType.resourceTypeFileOrDirectory, Category.categoryRun, CommandType.commandTypeExecute, "open -a Terminal ${easyshell:container_loc}")); // MAC OS X Finder - list.add(new CommandData("f6bcdd71-4687-46d8-bf34-2780bafd762a", PresetType.presetPlugin, OS.osMacOSX, "Finder", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeExplore, + list.add(new CommandData("f6bcdd71-4687-46d8-bf34-2780bafd762a", PresetType.presetPlugin, OS.osMacOSX, "Finder", ResourceType.resourceTypeFileOrDirectory, Category.categoryExplore, CommandType.commandTypeExecute, "open -R ${easyshell:resource_loc}")); // MAC OS X Clipboard - list.add(new CommandData("cd32fa5a-34d7-4551-8bd0-3aae0dc444d0", PresetType.presetPlugin, OS.osMacOSX, "Full path", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeClipboard, + list.add(new CommandData("cd32fa5a-34d7-4551-8bd0-3aae0dc444d0", PresetType.presetPlugin, OS.osMacOSX, "Full path", ResourceType.resourceTypeFileOrDirectory, Category.categoryClipboard, CommandType.commandTypeClipboard, "${easyshell:resource_loc}${easyshell:line_separator}")); } @@ -200,39 +201,39 @@ private static List getDefaultCommands() { case osUnknown: break; case osWindows: - addNotNull(listDefault, getCommandData(listOS, "DOS-Shell", CommandType.commandTypeOpen)); - addNotNull(listDefault, getCommandData(listOS, "DOS-Shell", CommandType.commandTypeRun)); - addNotNull(listDefault, getCommandData(listOS, "Explorer", CommandType.commandTypeExplore)); + addNotNull(listDefault, getCommandData(listOS, "DOS-Shell", Category.categoryOpen)); + addNotNull(listDefault, getCommandData(listOS, "DOS-Shell", Category.categoryRun)); + addNotNull(listDefault, getCommandData(listOS, "Explorer", Category.categoryExplore)); break; case osLinux: // add default preset for all desktops (XDG-open) - addNotNull(listDefault, getCommandData(listOS, ".*", CommandType.commandTypeDefault)); + addNotNull(listDefault, getCommandData(listOS, ".*", Category.categoryDefault)); // try to detect the desktop LinuxDesktop desktop = Utils.detectLinuxDesktop(); //Activator.getDefault().sysout(true, "Detected linux (Unix) desktop: >" + desktop.getName() + "<"); switch (desktop) { - case desktopKde: addNotNull(listDefault, getCommandData(listOS, ".*KDE.*", CommandType.commandTypeOpen)); - addNotNull(listDefault, getCommandData(listOS, ".*KDE.*", CommandType.commandTypeRun)); - //addNotNull(listDefault, getCommandData(listOS, "Dolphin", CommandType.commandTypeExplore)); + case desktopKde: addNotNull(listDefault, getCommandData(listOS, ".*KDE.*", Category.categoryOpen)); + addNotNull(listDefault, getCommandData(listOS, ".*KDE.*", Category.categoryRun)); + //addNotNull(listDefault, getCommandData(listOS, "Dolphin", Category.categoryExplore)); break; - case desktopCinnamon: addNotNull(listDefault, getCommandData(listOS, ".*Gnome.*", CommandType.commandTypeOpen)); - addNotNull(listDefault, getCommandData(listOS, ".*Gnome.*", CommandType.commandTypeRun)); - //addNotNull(listDefault, getCommandData(listOS, "Nemo", CommandType.commandTypeExplore)); + case desktopCinnamon: addNotNull(listDefault, getCommandData(listOS, ".*Gnome.*", Category.categoryOpen)); + addNotNull(listDefault, getCommandData(listOS, ".*Gnome.*", Category.categoryRun)); + //addNotNull(listDefault, getCommandData(listOS, "Nemo", Category.categoryExplore)); break; - case desktopGnome: addNotNull(listDefault, getCommandData(listOS, ".*Gnome.*", CommandType.commandTypeOpen)); - addNotNull(listDefault, getCommandData(listOS, ".*Gnome.*", CommandType.commandTypeRun)); - //addNotNull(listDefault, getCommandData(listOS, "Nautilus", CommandType.commandTypeExplore)); + case desktopGnome: addNotNull(listDefault, getCommandData(listOS, ".*Gnome.*", Category.categoryOpen)); + addNotNull(listDefault, getCommandData(listOS, ".*Gnome.*", Category.categoryRun)); + //addNotNull(listDefault, getCommandData(listOS, "Nautilus", Category.categoryExplore)); break; - case desktopXfce: addNotNull(listDefault, getCommandData(listOS, ".*Xfce.*", CommandType.commandTypeOpen)); - addNotNull(listDefault, getCommandData(listOS, ".*Xfce.*", CommandType.commandTypeRun)); - //addNotNull(listDefault, getCommandData(listOS, "Thunar", CommandType.commandTypeExplore)); + case desktopXfce: addNotNull(listDefault, getCommandData(listOS, ".*Xfce.*", Category.categoryOpen)); + addNotNull(listDefault, getCommandData(listOS, ".*Xfce.*", Category.categoryRun)); + //addNotNull(listDefault, getCommandData(listOS, "Thunar", Category.categoryExplore)); break; default:; } // try to detect the default file browser if (desktop != LinuxDesktop.desktopUnknown) { Map fileBrowsers = new HashMap(); - for (CommandData data : getCommandDataList(listOS, CommandType.commandTypeExplore)) { + for (CommandData data : getCommandDataList(listOS, Category.categoryExplore)) { fileBrowsers.put("(?i).*" + data.getName() + ".*", data); } Object fileBrowser = Utils.detectLinuxDefaultFileBrowser(fileBrowsers); @@ -244,13 +245,13 @@ private static List getDefaultCommands() { } break; case osMacOSX: - addNotNull(listDefault, getCommandData(listOS, "Terminal", CommandType.commandTypeOpen)); - addNotNull(listDefault, getCommandData(listOS, "Terminal", CommandType.commandTypeRun)); - addNotNull(listDefault, getCommandData(listOS, "Finder", CommandType.commandTypeExplore)); + addNotNull(listDefault, getCommandData(listOS, "Terminal", Category.categoryOpen)); + addNotNull(listDefault, getCommandData(listOS, "Terminal", Category.categoryRun)); + addNotNull(listDefault, getCommandData(listOS, "Finder", Category.categoryExplore)); break; } // add clipboard - addNotNull(listDefault, getCommandData(listOS, ".*path", CommandType.commandTypeClipboard)); + addNotNull(listDefault, getCommandData(listOS, ".*path", Category.categoryClipboard)); return listDefault; } @@ -276,19 +277,19 @@ public static List getCommandData(List list, OS os, bo return listOut; } - private static CommandData getCommandData(List list, String name, CommandType type) { + private static CommandData getCommandData(List list, String name, Category category) { for (CommandData entry : list) { - if (entry.getCommandType() == type && entry.getName().matches(name)) { + if (entry.getCategory() == category && entry.getName().matches(name)) { return entry; } } return null; } - private static List getCommandDataList(List list, CommandType type) { + private static List getCommandDataList(List list, Category category) { List listOut = new ArrayList(); for (CommandData entry : list) { - if (entry.getCommandType() == type) { + if (entry.getCategory() == category) { CommandData newData = new CommandData(entry, false); listOut.add(newData); } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java index 9878112a..0068e85d 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java @@ -34,6 +34,7 @@ import de.anbos.eclipse.easyshell.plugin.Activator; import de.anbos.eclipse.easyshell.plugin.Utils; +import de.anbos.eclipse.easyshell.plugin.types.Category; import de.anbos.eclipse.easyshell.plugin.types.CommandType; import de.anbos.eclipse.easyshell.plugin.types.ResourceType; @@ -41,8 +42,9 @@ public class CommandDataDialog extends StatusDialog { private CommandData data; private boolean edit; - private Combo resourceTypeCombo; - private Combo commandTypeCombo; + private Combo resourceTypeCombo; + private Combo categoryCombo; + private Combo commandTypeCombo; private Text nameText; private Button dirCheckBox; private Text dirText; @@ -96,6 +98,8 @@ public Control createDialogArea(Composite parent) { pageGroup1.setFont(parent.getFont()); // create resource type combo createResourceTypeCombo(pageGroup1); + // create category combo + createCategoryCombo(pageGroup1); // create command type combo createCommandTypeCombo(pageGroup1); //create input nameText field @@ -132,6 +136,8 @@ public Control createDialogArea(Composite parent) { refreshDirCheckBox(); + refreshCategoryCombo(); + refreshCommandTypeCombo(); return pageComponent; @@ -208,6 +214,13 @@ private void refreshResourceTypeCombo() { resourceTypeCombo.notifyListeners(SWT.Selection, event); } + private void refreshCategoryCombo() { + // send event to refresh + Event event = new Event(); + event.item = null; + categoryCombo.notifyListeners(SWT.Selection, event); + } + private void refreshCommandTypeCombo() { // send event to refresh Event event = new Event(); @@ -227,11 +240,12 @@ protected void okPressed() { if (!validateValues()) { return; } - data.setResourceType(ResourceType.getFromName(resourceTypeCombo.getText())); - data.setCommandType(CommandType.getFromName(commandTypeCombo.getText())); data.setName(nameText.getText()); + data.setResourceType(ResourceType.getFromName(resourceTypeCombo.getText())); data.setUseWorkingDirectory(dirCheckBox.getSelection()); data.setWorkingDirectory(dirText.getText()); + data.setCategory(Category.getFromName(categoryCombo.getText())); + data.setCommandType(CommandType.getFromName(commandTypeCombo.getText())); data.setCommand(valueText.getText()); } super.okPressed(); @@ -247,7 +261,13 @@ private boolean validateValues() { return false; } - // check type + // check command type + if ( (categoryCombo.getText() == null) || (categoryCombo.getText().length() <= 0)) { + MessageDialog.openError(getShell(), title, Activator.getResourceString("easyshell.command.editor.dialog.error.text.category")); + return false; + } + + // check command type if ( (commandTypeCombo.getText() == null) || (commandTypeCombo.getText().length() <= 0)) { MessageDialog.openError(getShell(), title, Activator.getResourceString("easyshell.command.editor.dialog.error.text.type")); return false; @@ -286,7 +306,7 @@ private boolean validateValues() { private void createResourceTypeCombo(Composite parent) { // draw label - createLabel(parent, Activator.getResourceString("easyshell.command.editor.dialog.label.combo2")); + createLabel(parent, Activator.getResourceString("easyshell.command.editor.dialog.label.combo.resource")); createLabel(parent, ""); // draw combo resourceTypeCombo = new Combo(parent,SWT.BORDER | SWT.READ_ONLY); @@ -314,9 +334,38 @@ public void widgetDefaultSelected(SelectionEvent e) { resourceTypeCombo.setEnabled(edit); } + private void createCategoryCombo(Composite parent) { + // draw label + createLabel(parent, Activator.getResourceString("easyshell.command.editor.dialog.label.combo.category")); + createLabel(parent, ""); + // draw combo + categoryCombo = new Combo(parent,SWT.BORDER | SWT.READ_ONLY); + categoryCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + categoryCombo.setItems(Category.getNamesAsArray()); + categoryCombo.select(0); + categoryCombo.addSelectionListener(new SelectionListener() { + @Override + public void widgetSelected(SelectionEvent e) { + //String text = typeCombo.getItem(typeCombo.getSelectionIndex()); + } + @Override + public void widgetDefaultSelected(SelectionEvent e) { + // TODO Auto-generated method stub + } + }); + String[] items = categoryCombo.getItems(); + for(int i = 0 ; i < items.length ; i++) { + if(items[i].equals(this.data.getCategory().getName())) { + categoryCombo.select(i); + return; + } + } + categoryCombo.setEnabled(edit); + } + private void createCommandTypeCombo(Composite parent) { // draw label - createLabel(parent, Activator.getResourceString("easyshell.command.editor.dialog.label.combo1")); + createLabel(parent, Activator.getResourceString("easyshell.command.editor.dialog.label.combo.type")); createLabel(parent, ""); // draw combo commandTypeCombo = new Combo(parent,SWT.BORDER | SWT.READ_ONLY); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataLabelProvider.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataLabelProvider.java index f661d46e..6d254297 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataLabelProvider.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataLabelProvider.java @@ -26,7 +26,7 @@ public Image getColumnImage(Object element, int columnIndex) { CommandData data = (CommandData)element; switch(columnIndex) { case 0: - return new Image(null, Activator.getImageDescriptor(data.getCommandType().getIcon()).getImageData()); + return new Image(null, Activator.getImageDescriptor(data.getCategory().getIcon()).getImageData()); default: return null; } @@ -39,7 +39,7 @@ public String getColumnText(Object element, int columnIndex) { CommandData data = (CommandData)element; switch(columnIndex) { case 0: - return data.getCommandType().getName(); + return data.getCategory().getName(); case 1: return data.getName(); case 2: diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java index 94f2d0b8..02fa0760 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java @@ -45,6 +45,7 @@ import de.anbos.eclipse.easyshell.plugin.Activator; import de.anbos.eclipse.easyshell.plugin.Utils; +import de.anbos.eclipse.easyshell.plugin.types.Category; import de.anbos.eclipse.easyshell.plugin.types.CommandType; import de.anbos.eclipse.easyshell.plugin.types.PresetType; import de.anbos.eclipse.easyshell.plugin.types.ResourceType; @@ -368,7 +369,7 @@ private void addDialog(CommandData data, boolean copy) { } private void addNewDialog() { - CommandData dataNew = new CommandData(null, PresetType.presetUser, Utils.getOS(), "MyNewCommand", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOther, "my_new_command"); + CommandData dataNew = new CommandData(null, PresetType.presetUser, Utils.getOS(), "MyNewCommand", ResourceType.resourceTypeFileOrDirectory, Category.categoryOther, CommandType.commandTypeExecute, "my_new_command"); addDialog(dataNew, false); } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandTableFilter.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandTableFilter.java index c91d465d..98384034 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandTableFilter.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandTableFilter.java @@ -29,7 +29,7 @@ public boolean select(Viewer viewer, Object parentElement, Object element) { return true; } CommandData data = (CommandData) element; - if (data.getCommandType().getName().matches(searchString)) { + if (data.getCategory().getName().matches(searchString)) { return true; } if (data.getName().matches(searchString)) { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java index e64f1edc..8cd90db3 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java @@ -70,7 +70,12 @@ public String getNamePattern() { } public String getNameExpanded() { - return namePattern.replace("${easyshell:command_type}", getCommandData().getCommandType().getName()).replace("${easyshell:command_name}", getCommandData().getName()).replace("${easyshell:command_os}", getCommandData().getOs().getName()); + String expanded = namePattern; + expanded = expanded.replace("${easyshell:command_category}", getCommandData().getCategory().getName()); + expanded = expanded.replace("${easyshell:command_type}", getCommandData().getCommandType().getName()); + expanded = expanded.replace("${easyshell:command_name}", getCommandData().getName()); + expanded = expanded.replace("${easyshell:command_os}", getCommandData().getOs().getName()); + return expanded; } public CommandData getCommandData() { @@ -130,6 +135,13 @@ public boolean deserialize(Version version, String value, StringTokenizer tokeni if (nameType == MenuNameType.menuNameTypeUser) { setNamePattern(namePatternReaded); } + } else if (version.getId() < Version.v2_0_003.getId()) { + setNameType(nameType); + if (nameType == MenuNameType.menuNameTypeUser) { + setNamePattern(namePatternReaded); + } else { + setNamePattern(nameType.getPattern()); + } } else { setNameType(nameType); setNamePattern(namePatternReaded); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java index 0cc5219e..76a64c21 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java @@ -38,6 +38,7 @@ import de.anbos.eclipse.easyshell.plugin.Activator; import de.anbos.eclipse.easyshell.plugin.Utils; +import de.anbos.eclipse.easyshell.plugin.types.Category; import de.anbos.eclipse.easyshell.plugin.types.CommandType; import de.anbos.eclipse.easyshell.plugin.types.PresetType; import de.anbos.eclipse.easyshell.plugin.types.ResourceType; @@ -272,7 +273,7 @@ private void removeCommand(int index, CommandData data) { } private void addNewDialog() { - CommandData data = new CommandData(null, PresetType.presetUser, Utils.getOS(), "MyNewCommand", ResourceType.resourceTypeFileOrDirectory, CommandType.commandTypeOther, "my_new_command"); + CommandData data = new CommandData(null, PresetType.presetUser, Utils.getOS(), "MyNewCommand", ResourceType.resourceTypeFileOrDirectory, Category.categoryOther, CommandType.commandTypeExecute, "my_new_command"); addDialog(data, false); } @@ -369,7 +370,7 @@ private void createEnabledCheckBox(Composite parent) { } private String getCommandAsComboName(CommandData data) { - return data.getPresetType().getName() + " - " + data.getOs().getName() + " - " + data.getCommandType().getName() + " - " + data.getName(); + return data.getPresetType().getName() + " - " + data.getOs().getName() + " - " + data.getCategory().getName() + " - " + data.getName(); } private String[] getAllCommandsAsComboNames(List list) { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataLabelProvider.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataLabelProvider.java index 06b8480b..f64c5459 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataLabelProvider.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataLabelProvider.java @@ -26,7 +26,7 @@ public Image getColumnImage(Object element, int columnIndex) { MenuData data = (MenuData)element; switch(columnIndex) { case 0: - return new Image(null, Activator.getImageDescriptor(data.getCommandData().getCommandType().getIcon()).getImageData()); + return new Image(null, Activator.getImageDescriptor(data.getCommandData().getCategory().getIcon()).getImageData()); default: return null; } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Category.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Category.java new file mode 100644 index 00000000..a6ab7512 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Category.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.types; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import de.anbos.eclipse.easyshell.plugin.Constants; + +public enum Category { + categoryUnknown(-1, "Unknown", Constants.IMAGE_UNKNOWN), + categoryDefault(0, "Default", Constants.IMAGE_DEFAULT), + categoryOpen(1, "Open", Constants.IMAGE_OPEN), + categoryRun(2, "Run", Constants.IMAGE_RUN), + categoryExplore(3, "Explore", Constants.IMAGE_EXPLORE), + categoryClipboard(4, "Clipboard", Constants.IMAGE_CLIPBOARD), + categoryOther(5, "Other", Constants.IMAGE_OTHER); + // attributes + private final int id; + private final String name; + private final String icon; + // construct + Category(int id, String name, String icon) { + this.id = id; + this.name = name; + this.icon = icon; + } + public int getId() { + return id; + } + public String getName() { + return name; + } + public String getIcon() { + return icon; + } + public static Category getFromId(int id) { + Category ret = categoryUnknown; + for(int i = 0; i < Category.values().length; i++) { + if (Category.values()[i].getId() == id) { + ret = Category.values()[i]; + break; + } + } + return ret; + } + public static Category getFromName(String name) { + Category ret = categoryUnknown; + for(int i = 0; i < Category.values().length; i++) { + if (Category.values()[i].getName().equals(name)) { + ret = Category.values()[i]; + break; + } + } + return ret; + } + public static Category getFromEnum(String name) { + return Category.valueOf(name); + } + public static Category getFromDeprecatedCommandTypeEnum(String name) { + // set mapping + Map map = new HashMap(); + map.put("commandTypeOpen", categoryOpen); + map.put("commandTypeRun", categoryRun); + map.put("commandTypeExplore", categoryExplore); + map.put("commandTypeClipboard", categoryClipboard); + map.put("commandTypeOther", categoryOther); + // find the key + for(String key: map.keySet()) { + if (name.equals(key)) { + return (Category)map.get(key); + } + } + return categoryUnknown; + } + + public static List getNamesAsList() { + List list = new ArrayList(); + for(int i = 0; i < Category.values().length; i++) { + if (Category.values()[i] != categoryUnknown) { + list.add(Category.values()[i].getName()); + } + } + return list; + } + public static String[] getNamesAsArray() { + List list = getNamesAsList(); + String[] arr = new String[list.size()]; + for (int i=0;i getIconsAsList() { + List list = new ArrayList(); + for(int i = 0; i < Category.values().length; i++) { + if (Category.values()[i] != categoryUnknown) { + list.add(Category.values()[i].getIcon()); + } + } + return list; + } +} \ No newline at end of file diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/CommandType.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/CommandType.java index 0c25be10..19b545e1 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/CommandType.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/CommandType.java @@ -12,28 +12,24 @@ package de.anbos.eclipse.easyshell.plugin.types; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import de.anbos.eclipse.easyshell.plugin.Constants; public enum CommandType { - commandTypeUnknown(-1, "Unknown", Constants.IMAGE_UNKNOWN, Constants.ACTION_UNKNOWN), - commandTypeDefault(0, "Default", Constants.IMAGE_DEFAULT, Constants.ACTION_DEFAULT), - commandTypeOpen(1, "Open", Constants.IMAGE_OPEN, Constants.ACTION_OPEN), - commandTypeRun(2, "Run", Constants.IMAGE_RUN, Constants.ACTION_RUN), - commandTypeExplore(3, "Explore", Constants.IMAGE_EXPLORE, Constants.ACTION_EXPLORE), - commandTypeClipboard(4, "Clipboard", Constants.IMAGE_CLIPBOARD, Constants.ACTION_CLIPBOARD), - commandTypeOther(5, "Other", Constants.IMAGE_OTHER, Constants.ACTION_OTHER); + commandTypeUnknown(-1, "Unknown", Constants.ACTION_UNKNOWN), + commandTypeExecute(0, "Execute", Constants.ACTION_EXECUTE), + commandTypeClipboard(1, "Clipboard", Constants.ACTION_CLIPBOARD); // attributes private final int id; private final String name; - private final String icon; private final String action; // construct - CommandType(int id, String name, String icon, String action) { + CommandType(int id, String name, String action) { this.id = id; this.name = name; - this.icon = icon; this.action = action; } public int getId() { @@ -42,9 +38,6 @@ public int getId() { public String getName() { return name; } - public String getIcon() { - return icon; - } public String getAction() { return action; } @@ -71,6 +64,22 @@ public static CommandType getFromName(String name) { public static CommandType getFromEnum(String name) { return CommandType.valueOf(name); } + public static CommandType getFromDeprecatedCommandTypeEnum(String name) { + // set mapping + Map map = new HashMap(); + map.put("commandTypeOpen", commandTypeExecute); + map.put("commandTypeRun", commandTypeExecute); + map.put("commandTypeExplore", commandTypeExecute); + map.put("commandTypeClipboard", commandTypeClipboard); + map.put("commandTypeOther", commandTypeExecute); + // find the key + for(String key: map.keySet()) { + if (name.equals(key)) { + return (CommandType)map.get(key); + } + } + return commandTypeUnknown; + } public static CommandType getFromAction(String action) { CommandType ret = commandTypeUnknown; for(int i = 0; i < CommandType.values().length; i++) { @@ -98,15 +107,6 @@ public static String[] getNamesAsArray() { } return arr; } - public static List getIconsAsList() { - List list = new ArrayList(); - for(int i = 0; i < CommandType.values().length; i++) { - if (CommandType.values()[i] != commandTypeUnknown) { - list.add(CommandType.values()[i].getIcon()); - } - } - return list; - } public static List getActionsAsList() { List list = new ArrayList(); for(int i = 0; i < CommandType.values().length; i++) { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/MenuNameType.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/MenuNameType.java index e12da40a..52e9601c 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/MenuNameType.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/MenuNameType.java @@ -17,9 +17,9 @@ public enum MenuNameType { menuNameTypeUnknown(-1, "Unknown", ""), menuNameTypeUser(0, "User defined", "${easyshell:command_name}"), - menuNameTypeGeneric1(1, ": ", "${easyshell:command_type}: ${easyshell:command_name}"), - menuNameTypeGeneric2(2, " with ", "${easyshell:command_type} with ${easyshell:command_name}"), - menuNameTypeGeneric3(3, " with ", "${easyshell:command_type} with ${easyshell:command_os} ${easyshell:command_name}"); + menuNameTypeGeneric1(1, ": ", "${easyshell:command_category}: ${easyshell:command_name}"), + menuNameTypeGeneric2(2, " with ", "${easyshell:command_category} with ${easyshell:command_name}"), + menuNameTypeGeneric3(3, " with ", "${easyshell:command_category} with ${easyshell:command_os} ${easyshell:command_name}"); // attributes private final int id; private final String name; From 70ab4f8ffb016c415b39626b00852a09fd26a906 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Tue, 26 Jul 2016 16:15:56 +0200 Subject: [PATCH 31/73] #58 [v2.0] deletion of command that is used in more then one menu Signed-off-by: Andre Bossert --- .../easyshell/plugin/UIMessages.properties | 10 ++- .../plugin/commands/DefineCommands.java | 5 +- .../plugin/preferences/CommandData.java | 4 + .../plugin/preferences/CommandDataStore.java | 10 +++ .../plugin/preferences/CommandPage.java | 67 +++++++++++---- .../plugin/preferences/MenuData.java | 1 + .../plugin/preferences/MenuDataDialog.java | 84 ++++++++++++++----- .../plugin/preferences/MenuDataStore.java | 22 +++++ .../plugin/preferences/MenuPage.java | 82 ++++++++++-------- 9 files changed, 209 insertions(+), 76 deletions(-) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties index ab203109..d8f034e5 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties @@ -29,7 +29,7 @@ easyshell.menu.page.button.tooltip.up=Move selected menu up easyshell.menu.page.button.text.down=Down easyshell.menu.page.button.tooltip.down=Move selected menu down easyshell.menu.page.dialog.remove.title=Remove menu(s) -easyshell.menu.page.dialog.remove.question=Do you really want to remove selected menu(s) ? +easyshell.menu.page.dialog.remove.question=Do you really want to remove selected menu(s):\n\n{0} easyshell.menu.page.dialog.defaults.title=Restore defaults easyshell.menu.page.dialog.defaults.question=All your menu definitions will be overwritten!\n\nYou can still use "Cancel" button afterwards for undo.\n\nDo you really want to restore default settings? @@ -51,7 +51,9 @@ easyshell.command.page.button.tooltip.edit=Show or edit selected command easyshell.command.page.button.text.remove=Remove... easyshell.command.page.button.tooltip.remove=Remove selected commands(s) easyshell.command.page.dialog.remove.title=Remove command(s) -easyshell.command.page.dialog.remove.question=Do you really want to remove selected command(s) ? +easyshell.command.page.dialog.remove.question=Do you really want to remove selected command(s):\n\n{0} +easyshell.command.page.dialog.remove.menu.title=Remove command(s) and menu(s) +easyshell.command.page.dialog.remove.menu.question=The selected command(s):\n\n{0}\nis(are) used in menu(s):\n\n{1}\nDo you really want to remove selected command(s) and menu(s) ? easyshell.command.page.dialog.defaults.title=Restore defaults easyshell.command.page.dialog.defaults.question=All your command definitions will be overwritten!\n\nYou can still use "Cancel" button afterwards for undo.\n\nDo you really want to restore default settings? @@ -81,6 +83,10 @@ easyshell.menu.editor.dialog.button.text.remove=Remove... easyshell.menu.editor.dialog.button.tooltip.remove=Remove selected command easyshell.menu.editor.dialog.title.remove=Remove command easyshell.menu.editor.dialog.question.remove=Do you really want to remove command\n"{0}" ? +easyshell.menu.editor.dialog.title.remove.menu=Remove command and menu(s) +easyshell.menu.editor.dialog.question.remove.menu=The selected command:\n\n{0}\n\nis used in other menu(s):\n\n{1}\nDo you really want to remove selected command and menu(s) ? +easyshell.menu.editor.dialog.title.duplicate=Duplicate usage of command +easyshell.menu.editor.dialog.question.duplicate=The selected command:\n\n{0}\n\nis used in other menu(s) already:\n\n{1}\nDo you really want to use the same command in this menu ? easyshell.command.editor.dialog.title.new=Create new command easyshell.command.editor.dialog.title.copy=Copy to new command diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java index e4ba2769..95147dfc 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java @@ -36,9 +36,8 @@ public void createContributionItems(IServiceLocator serviceLocator, IContributionRoot additions) { // load the preferences - MenuDataStore store = new MenuDataStore(Activator.getDefault().getPreferenceStore()); - store.load(); - List items = store.getEnabledCommandMenuDataList(); + MenuDataStore.instance().load(); + List items = MenuDataStore.instance().getEnabledCommandMenuDataList(); for (MenuData item : items) { addItem(serviceLocator, additions, item.getNameExpanded(), diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java index a0794277..a3030c5a 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java @@ -98,6 +98,10 @@ public String getCommand() { return command; } + public String getCommandAsComboName() { + return getCategory().getName() + " - " + getName() + " (" + getPresetType().getName() + ")" /*+ getOs().getName() + " - "*/; + } + public void setName(String name) { this.name = name; } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataStore.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataStore.java index 34975c90..58355fd5 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataStore.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataStore.java @@ -16,11 +16,21 @@ import org.eclipse.jface.preference.IPreferenceStore; +import de.anbos.eclipse.easyshell.plugin.Activator; import de.anbos.eclipse.easyshell.plugin.Constants; import de.anbos.eclipse.easyshell.plugin.types.PresetType; public class CommandDataStore extends DataStore { + private static CommandDataStore instance = null; + + public static CommandDataStore instance() { + if (instance == null) { + instance = new CommandDataStore(Activator.getDefault().getPreferenceStore()); + } + return instance; + } + public CommandDataStore(IPreferenceStore store) { super(store); } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java index 02fa0760..de112267 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java @@ -11,7 +11,11 @@ package de.anbos.eclipse.easyshell.plugin.preferences; +import java.text.MessageFormat; +import java.util.ArrayList; import java.util.Iterator; +import java.util.List; + import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; @@ -53,7 +57,6 @@ public class CommandPage extends org.eclipse.jface.preference.PreferencePage implements IWorkbenchPreferencePage { - private CommandDataStore commandStore; private Text searchText; private CommandTableFilter filter; private TableViewer tableViewer; @@ -69,7 +72,7 @@ public void init(IWorkbench workbench) { @Override public boolean performOk() { boolean save = true; - if (!commandStore.isMigrated()) { + if (!CommandDataStore.instance().isMigrated()) { String title = Activator.getResourceString("easyshell.command.page.dialog.migration.title"); String question = Activator.getResourceString("easyshell.command.page.dialog.migration.question"); MessageDialog dialog = new MessageDialog( @@ -79,13 +82,13 @@ public boolean performOk() { 1); // no is the default int result = dialog.open(); if (result == 0) { - commandStore.setMigrated(true); + CommandDataStore.instance().setMigrated(true); } else { save = false; } } if (save) { - commandStore.save(); + CommandDataStore.instance().save(); } return save; } @@ -101,7 +104,7 @@ protected void performDefaults() { 1); // no is the default int result = dialog.open(); if (result == 0) { - commandStore.loadDefaults(); + CommandDataStore.instance().loadDefaults(); tableViewer.refresh(); } } @@ -123,8 +126,10 @@ protected Control createContents(Composite parent) { createSearchField(pageComponent); // command store - commandStore = new CommandDataStore(Activator.getDefault().getPreferenceStore()); - commandStore.load(); + CommandDataStore.instance().load(); + + // menu store + MenuDataStore.instance().load(); // table viewer createTableViewer(pageComponent); @@ -212,7 +217,7 @@ private void createTableViewer(Composite parent) { // Get the content for the viewer, setInput will call getElements in the // contentProvider - tableViewer.setInput(commandStore); + tableViewer.setInput(CommandDataStore.instance()); // Layout the viewer GridData gridData = new GridData(); @@ -361,7 +366,7 @@ private void addDialog(CommandData data, boolean copy) { } CommandDataDialog dialog = new CommandDataDialog(getShell(), data, title, true); if (dialog.open() == Window.OK) { - commandStore.add(data); + CommandDataStore.instance().add(data); refreshTableViewer(data); } else { data = null; @@ -389,7 +394,7 @@ private void editDialog() { dataNew.setPosition(dataSelected.getPosition()); CommandDataDialog dialog = new CommandDataDialog(getShell(), dataNew, Activator.getResourceString("easyshell.command.editor.dialog.title.edit"), true); if (dialog.open() == Window.OK) { - commandStore.replace(dataNew); + CommandDataStore.instance().replace(dataNew); refreshTableViewer(dataNew); } else { dataNew = null; @@ -401,20 +406,48 @@ private void editDialog() { } private void removeDialog() { + // get the selected commands and referenced menus as lists + List commands = new ArrayList(); + List menus = new ArrayList(); + IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection(); + Iterator elements = selection.iterator(); + while (elements.hasNext()) { + CommandData data = (CommandData) elements.next(); + commands.add(data); + List menusForOne = MenuDataStore.instance().getRefencedBy(data.getId()); + menus.addAll(menusForOne); + } + // ask user + String commandNames = ""; + for (CommandData command : commands) { + commandNames += command.getCommandAsComboName() + "\n"; + } String title = Activator.getResourceString("easyshell.command.page.dialog.remove.title"); - String question = Activator.getResourceString("easyshell.command.page.dialog.remove.question"); + String question = MessageFormat.format(Activator.getResourceString("easyshell.command.page.dialog.remove.question"), + commandNames); + int dialogImageType = MessageDialog.QUESTION; + if (menus.size() > 0) { + dialogImageType = MessageDialog.WARNING; + title = Activator.getResourceString("easyshell.command.page.dialog.remove.menu.title"); + String menuNames = ""; + for (MenuData menu : menus) { + menuNames += menu.getNameExpanded() + "\n"; + } + question = MessageFormat.format(Activator.getResourceString("easyshell.command.page.dialog.remove.menu.question"), + commandNames, menuNames); + } MessageDialog dialog = new MessageDialog( null, title, null, question, - MessageDialog.QUESTION, + dialogImageType, new String[] {"Yes", "No"}, 1); // no is the default int result = dialog.open(); if (result == 0) { - IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection(); - Iterator elements = selection.iterator(); - while (elements.hasNext()) { - CommandData data = (CommandData) elements.next(); - commandStore.delete(data); + for (MenuData menu : menus) { + MenuDataStore.instance().delete(menu); + } + for (CommandData command : commands) { + CommandDataStore.instance().delete(command); } tableViewer.refresh(); } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java index 8cd90db3..8c156810 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java @@ -46,6 +46,7 @@ public MenuData(CommandData commandData, boolean generateNewId) { public MenuData(String newId, MenuData data) { this(newId, data.getCommandData()); + this.enabled = data.isEnabled(); this.nameType = data.getNameType(); this.namePattern = data.getNamePattern(); } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java index 76a64c21..64dc03cb 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java @@ -12,10 +12,13 @@ package de.anbos.eclipse.easyshell.plugin.preferences; import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.StatusDialog; +import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; @@ -47,7 +50,6 @@ public class MenuDataDialog extends StatusDialog { private MenuData data; - private CommandDataStore cmdStore; private List cmdList; private Button enabledCheckBox; @@ -62,10 +64,9 @@ public class MenuDataDialog extends StatusDialog { private Button editButton; private Button removeButton; - public MenuDataDialog(Shell parent, MenuData data, CommandDataStore cmdStore, List cmdList, boolean edit) { + public MenuDataDialog(Shell parent, MenuData data, List cmdList, boolean edit) { super(parent); this.data = data; - this.cmdStore = cmdStore; this.cmdList = cmdList; // do layout and title setShellStyle(getShellStyle() | SWT.MAX); @@ -247,8 +248,8 @@ private void addDialog(CommandData data, boolean copy) { } private void addCommand(CommandData data) { - cmdStore.add(data); - cmdStore.save(); + CommandDataStore.instance().add(data); + CommandDataStore.instance().save(); cmdList.add(data); String[] names = getAllCommandsAsComboNames(cmdList); commandCombo.setItems(names); @@ -256,15 +257,15 @@ private void addCommand(CommandData data) { } private void replaceCommand(int index, CommandData data) { - cmdStore.replace(data); - cmdStore.save(); - commandCombo.setItem(index, getCommandAsComboName(data)); + CommandDataStore.instance().replace(data); + CommandDataStore.instance().save(); + commandCombo.setItem(index, data.getCommandAsComboName()); commandCombo.select(index); } private void removeCommand(int index, CommandData data) { - cmdStore.delete(data); - cmdStore.save(); + CommandDataStore.instance().delete(data); + CommandDataStore.instance().save(); //cmdList.remove(data); // no need to search for data, use index instead: cmdList.remove(index); String[] names = getAllCommandsAsComboNames(cmdList); @@ -304,19 +305,43 @@ private void editDialog() { } private void removeDialog() { + // get the selected commands and referenced menus as lists + List commands = new ArrayList(); + List menus = new ArrayList(); + // get the selected int index = commandCombo.getSelectionIndex(); + CommandData data = cmdList.get(index); + commands.add(data); + // get referenced menus and remove the the actual menus + menus.addAll(MenuDataStore.instance().getRefencedBy(data.getId())); + menus.remove(this.data); + // ask user + String commandNames = commandCombo.getItem(index); String title = Activator.getResourceString("easyshell.menu.editor.dialog.title.remove"); String question = MessageFormat.format( Activator.getResourceString("easyshell.menu.editor.dialog.question.remove"), - commandCombo.getItem(index)); + commandNames); + int dialogImageType = MessageDialog.QUESTION; + if (menus.size() > 0) { + dialogImageType = MessageDialog.WARNING; + title = Activator.getResourceString("easyshell.menu.editor.dialog.title.remove.menu"); + String menuNames = ""; + for (MenuData menu : menus) { + menuNames += menu.getNameExpanded() + "\n"; + } + question = MessageFormat.format(Activator.getResourceString("easyshell.menu.editor.dialog.question.remove.menu"), + commandNames, menuNames); + } MessageDialog dialog = new MessageDialog( null, title, null, question, - MessageDialog.QUESTION, + dialogImageType, new String[] {"Yes", "No"}, 1); // no is the default int result = dialog.open(); if (result == 0) { - CommandData data = cmdList.get(index); + for (MenuData menu : menus) { + MenuDataStore.instance().delete(menu); + } removeCommand(index, data); refreshCommandCombo(); } @@ -338,7 +363,7 @@ private void refreshNameTypeCombo() { private boolean validateValues() { - final String title = Activator.getResourceString("easyshell.menu.editor.dialog.error.incompletedata.title"); + String title = Activator.getResourceString("easyshell.menu.editor.dialog.error.incompletedata.title"); // check type if ( (commandCombo.getText() == null) || (commandCombo.getText().length() <= 0)) { @@ -357,7 +382,32 @@ private boolean validateValues() { // show error message if (!valid) { MessageDialog.openError(getShell(), title, text); + } else { + int index = commandCombo.getSelectionIndex(); + CommandData data = cmdList.get(index); + List menus = MenuDataStore.instance().getRefencedBy(data.getId()); + menus.remove(this.data); + if (menus.size() >0) { + title = Activator.getResourceString("easyshell.menu.editor.dialog.title.duplicate"); + String commandNames = commandCombo.getItem(index); + String menuNames = ""; + for (MenuData menu : menus) { + menuNames += menu.getNameExpanded() + "\n"; + } + String question = MessageFormat.format(Activator.getResourceString("easyshell.menu.editor.dialog.question.duplicate"), + commandNames, menuNames); + MessageDialog dialog = new MessageDialog( + null, title, null, question, + MessageDialog.WARNING, + new String[] {"Yes", "No"}, + 1); // no is the default + int result = dialog.open(); + if (result != 0) { + valid = false; + } + } } + return valid; } @@ -369,14 +419,10 @@ private void createEnabledCheckBox(Composite parent) { enabledCheckBox.setSelection(this.data.isEnabled()); } - private String getCommandAsComboName(CommandData data) { - return data.getPresetType().getName() + " - " + data.getOs().getName() + " - " + data.getCategory().getName() + " - " + data.getName(); - } - private String[] getAllCommandsAsComboNames(List list) { String[] arr = new String[list.size()]; for (int i=0;i { + private static MenuDataStore instance = null; + + public static MenuDataStore instance() { + if (instance == null) { + instance = new MenuDataStore(Activator.getDefault().getPreferenceStore()); + } + return instance; + } + public MenuDataStore(IPreferenceStore store) { super(store); } @@ -79,4 +89,16 @@ public void load() { sort(); } + public List getRefencedBy(String id) { + List ref = new ArrayList(); + Iterator dataIterator = getDataList().iterator(); + while(dataIterator.hasNext()) { + MenuData data = (MenuData)dataIterator.next(); + if(data.getCommandData().getId().equals(id)) { + ref.add(data); + } + } + return ref; + } + } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java index 9e9d61cf..10dd8d49 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java @@ -11,6 +11,8 @@ package de.anbos.eclipse.easyshell.plugin.preferences; +import java.text.MessageFormat; +import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -53,9 +55,7 @@ public class MenuPage extends org.eclipse.jface.preference.PreferencePage implements IWorkbenchPreferencePage { - private CommandDataStore commandStore; List commandList; - private MenuDataStore menuStore; private MenuDataMover itemMover; private Text searchText; private MenuTableFilter filter; @@ -74,7 +74,7 @@ public void init(IWorkbench workbench) { @Override public boolean performOk() { boolean save = true; - if (!menuStore.isMigrated()) { + if (!MenuDataStore.instance().isMigrated()) { String title = Activator.getResourceString("easyshell.menu.page.dialog.migration.title"); String question = Activator.getResourceString("easyshell.menu.page.dialog.migration.question"); MessageDialog dialog = new MessageDialog( @@ -84,13 +84,13 @@ public boolean performOk() { 1); // no is the default int result = dialog.open(); if (result == 0) { - menuStore.setMigrated(true); + MenuDataStore.instance().setMigrated(true); } else { save = false; } } if (save) { - menuStore.save(); + MenuDataStore.instance().save(); } return save; } @@ -106,7 +106,7 @@ protected void performDefaults() { 1); // no is the default int result = dialog.open(); if (result == 0) { - menuStore.loadDefaults(); + MenuDataStore.instance().loadDefaults(); refreshTableViewer(); } } @@ -128,15 +128,13 @@ protected Control createContents(Composite parent) { createSearchField(pageComponent); // command store - commandStore = new CommandDataStore(Activator.getDefault().getPreferenceStore()); - commandStore.load(); + CommandDataStore.instance().load(); // get the native commands list - commandList = CommandDataDefaultCollection.getCommandsNative(commandStore.getDataList(), true); + commandList = CommandDataDefaultCollection.getCommandsNative(CommandDataStore.instance().getDataList(), true); // menu store - menuStore = new MenuDataStore(Activator.getDefault().getPreferenceStore()); - menuStore.load(); + MenuDataStore.instance().load(); // table viewer createTableViewer(pageComponent); @@ -228,7 +226,7 @@ private void createTableViewer(Composite parent) { // Get the content for the viewer, setInput will call getElements in the // contentProvider - tableViewer.setInput(menuStore); + tableViewer.setInput(MenuDataStore.instance()); // Layout the viewer GridData gridData = new GridData(); @@ -291,7 +289,7 @@ public boolean isSorterProperty(Object element, String property) { } }); - itemMover = new MenuDataMover(table, menuStore); + itemMover = new MenuDataMover(table, MenuDataStore.instance()); } private void createColumns(final Composite parent, final TableViewer viewer) { @@ -403,10 +401,10 @@ public void widgetSelected(SelectionEvent event) { } private void addDialog(MenuData data) { - MenuDataDialog dialog = new MenuDataDialog(getShell(), data, commandStore, commandList, false); + MenuDataDialog dialog = new MenuDataDialog(getShell(), data, commandList, false); if (dialog.open() == Window.OK) { - menuStore.add(data); - refreshTableViewer(data); + MenuDataStore.instance().add(data); + refreshTableViewer(); } else { data = null; } @@ -429,32 +427,44 @@ private void editDialog() { MenuData dataSelected = (MenuData)selection.getFirstElement(); MenuData dataNew = new MenuData(dataSelected, false); dataNew.setPosition(dataSelected.getPosition()); - MenuDataDialog dialog = new MenuDataDialog(getShell(), dataNew, commandStore, commandList, true); + MenuDataDialog dialog = new MenuDataDialog(getShell(), dataNew, commandList, true); if (dialog.open() == Window.OK) { - menuStore.replace(dataNew); - refreshTableViewer(dataNew); + MenuDataStore.instance().replace(dataNew); + refreshTableViewer(); } else { dataNew = null; } } private void removeDialog() { - String title = Activator.getResourceString("easyshell.menu.page.dialog.remove.title"); - String question = Activator.getResourceString("easyshell.menu.page.dialog.remove.question"); - MessageDialog dialog = new MessageDialog( - null, title, null, question, - MessageDialog.QUESTION, - new String[] {"Yes", "No"}, - 1); // no is the default - int result = dialog.open(); - if (result == 0) { - IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection(); - Iterator elements = selection.iterator(); - while (elements.hasNext()) { - MenuData data = (MenuData) elements.next(); - menuStore.delete(data); + // get the selected menus as lists + List menus = new ArrayList(); + IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection(); + Iterator elements = selection.iterator(); + while (elements.hasNext()) { + MenuData data = (MenuData) elements.next(); + menus.add(data); + } + if (menus.size() > 0) { + String title = Activator.getResourceString("easyshell.menu.page.dialog.remove.title"); + String menuNames = ""; + for (MenuData menu : menus) { + menuNames += menu.getNameExpanded() + "\n"; + } + String question = MessageFormat.format(Activator.getResourceString("easyshell.menu.page.dialog.remove.question"), + menuNames); + MessageDialog dialog = new MessageDialog( + null, title, null, question, + MessageDialog.QUESTION, + new String[] {"Yes", "No"}, + 1); // no is the default + int result = dialog.open(); + if (result == 0) { + for (MenuData menu : menus) { + MenuDataStore.instance().delete(menu); + } + refreshTableViewer(); } - refreshTableViewer(); } } @@ -468,17 +478,19 @@ private void down() { tableViewer.refresh(); } + /* private void refreshTableViewer(MenuData data) { tableViewer.refresh(); tableViewer.setChecked(data, data.isEnabled()); tableViewer.setSelection(new StructuredSelection(data)); } + */ private void refreshTableViewer() { tableViewer.refresh(); // update/set checked elements tableViewer.setAllChecked(false); - tableViewer.setCheckedElements(menuStore.getEnabledCommandMenuDataArray()); + tableViewer.setCheckedElements(MenuDataStore.instance().getEnabledCommandMenuDataArray()); } } \ No newline at end of file From 81447506980a2ab548e5d61d100b3b76d113b652 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Tue, 26 Jul 2016 16:56:08 +0200 Subject: [PATCH 32/73] #61 [v2.0] remove the "?" (Help) buttons if there is no information Signed-off-by: Andre Bossert --- .../easyshell/plugin/preferences/CommandDataDialog.java | 3 +++ .../eclipse/easyshell/plugin/preferences/MenuDataDialog.java | 5 +++-- .../anbos/eclipse/easyshell/plugin/preferences/MenuPage.java | 1 - 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java index 0068e85d..3b55b06f 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java @@ -132,6 +132,9 @@ public Control createDialogArea(Composite parent) { createVariableLabel(pageGroup2, "${easyshell:project_name}", "is the project name"); createVariableLabel(pageGroup2, "${easyshell:line_separator}", "is the line separator"); + // TODO: to be enabled again, see https://github.com/anb0s/EasyShell/issues/61 + setHelpAvailable(false); + refreshResourceTypeCombo(); refreshDirCheckBox(); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java index 64dc03cb..0040e147 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java @@ -13,12 +13,10 @@ import java.text.MessageFormat; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.StatusDialog; -import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; @@ -153,6 +151,9 @@ public void modifyText(ModifyEvent e) { createLabel(pageGroup2, "");createLabel(pageGroup2, ""); createRemoveButton(font, pageGroup2, gridData2); + // TODO: to be enabled again, see https://github.com/anb0s/EasyShell/issues/61 + setHelpAvailable(false); + refreshCommandCombo(); return pageComponent; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java index 10dd8d49..f8490a93 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java @@ -25,7 +25,6 @@ import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; -import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TableViewerColumn; import org.eclipse.jface.viewers.Viewer; From 44f0bc322850bb56431ac9326233740f64d9b7fb Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Tue, 26 Jul 2016 17:17:17 +0200 Subject: [PATCH 33/73] #60 [v2.0] rename the "type" option to "category" - added icon showing Signed-off-by: Andre Bossert --- .../easyshell/plugin/preferences/CommandData.java | 6 ++++++ .../plugin/preferences/CommandDataDialog.java | 14 ++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java index a3030c5a..e5a9c20d 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java @@ -14,6 +14,9 @@ import java.util.StringTokenizer; import java.util.UUID; +import org.eclipse.swt.graphics.Image; + +import de.anbos.eclipse.easyshell.plugin.Activator; import de.anbos.eclipse.easyshell.plugin.types.Category; import de.anbos.eclipse.easyshell.plugin.types.CommandType; import de.anbos.eclipse.easyshell.plugin.types.OS; @@ -98,6 +101,9 @@ public String getCommand() { return command; } + public Image getCategoryImage() { + return new Image(null, Activator.getImageDescriptor(getCategory().getIcon()).getImageData()); + } public String getCommandAsComboName() { return getCategory().getName() + " - " + getName() + " (" + getPresetType().getName() + ")" /*+ getOs().getName() + " - "*/; } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java index 3b55b06f..42f0e1da 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java @@ -20,6 +20,7 @@ import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; @@ -43,6 +44,7 @@ public class CommandDataDialog extends StatusDialog { private CommandData data; private boolean edit; private Combo resourceTypeCombo; + private Label categoryImage; private Combo categoryCombo; private Combo commandTypeCombo; private Text nameText; @@ -152,6 +154,13 @@ private void createLabel(Composite parent, String name) { label.setText(name); } + private Label createImageLabel(Composite parent, String image) { + Label label = new Label(parent, SWT.LEFT); + label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END)); + label.setImage(new Image(null, Activator.getImageDescriptor(image).getImageData())); + return label; + } + private void createDirCheckBox(Composite parent) { // draw label createLabel(parent, Activator.getResourceString("easyshell.command.editor.dialog.label.useworkdir")); @@ -340,7 +349,7 @@ public void widgetDefaultSelected(SelectionEvent e) { private void createCategoryCombo(Composite parent) { // draw label createLabel(parent, Activator.getResourceString("easyshell.command.editor.dialog.label.combo.category")); - createLabel(parent, ""); + categoryImage = createImageLabel(parent, Category.categoryDefault.getIcon()); // draw combo categoryCombo = new Combo(parent,SWT.BORDER | SWT.READ_ONLY); categoryCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); @@ -349,7 +358,8 @@ private void createCategoryCombo(Composite parent) { categoryCombo.addSelectionListener(new SelectionListener() { @Override public void widgetSelected(SelectionEvent e) { - //String text = typeCombo.getItem(typeCombo.getSelectionIndex()); + String text = categoryCombo.getItem(categoryCombo.getSelectionIndex()); + categoryImage.setImage(new Image(null, Activator.getImageDescriptor(Category.getFromName(text).getIcon()).getImageData())); } @Override public void widgetDefaultSelected(SelectionEvent e) { From 248731ef6c95a65e372b89ba27ccf6c0e936f798 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Tue, 26 Jul 2016 23:04:12 +0200 Subject: [PATCH 34/73] refactoring of store and default values fixed #64 [v2.0] Execution error: c:\totalcmd\totalcmd64.exe /O /T ${easyshell:container_loc} Signed-off-by: Andre Bossert --- .../easyshell/plugin/UIMessages.properties | 1 + .../CommandDataDefaultCollection.java | 5 +- .../plugin/preferences/CommandDataStore.java | 13 +++ .../plugin/preferences/CommandPage.java | 45 +++++++-- .../plugin/preferences/DataStore.java | 9 ++ .../plugin/preferences/MenuData.java | 93 +++++++++++-------- .../plugin/preferences/MenuDataDialog.java | 10 +- .../plugin/preferences/MenuDataStore.java | 26 +++++- .../plugin/preferences/MenuPage.java | 13 +-- 9 files changed, 152 insertions(+), 63 deletions(-) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties index d8f034e5..05c7497b 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties @@ -57,6 +57,7 @@ easyshell.command.page.dialog.remove.menu.question=The selected command(s):\n\n{ easyshell.command.page.dialog.defaults.title=Restore defaults easyshell.command.page.dialog.defaults.question=All your command definitions will be overwritten!\n\nYou can still use "Cancel" button afterwards for undo.\n\nDo you really want to restore default settings? +easyshell.command.page.dialog.defaults.menu.question=All your command definitions will be overwritten!\n\nAdditionally also referenced menu(s) will be removed:\n\n{0}\n\nDo you really want to restore default settings? easyshell.command.page.dialog.migration.title=Migration easyshell.command.page.dialog.migration.question=You have canceled the migration of settings from previous version.\n\nAll your command definitions will be written now and migration will be skipped completely!\n\nDo you really want to overwrite the migrated settings? diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java index 5cb173bd..dccedca9 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java @@ -45,7 +45,8 @@ public static List getCommandsNativeAsMenu(boolean sorted) { List ret = new ArrayList(); for (int i=0;i getUserCommands() { @@ -67,17 +77,20 @@ public CommandData[] getAllCommandsArray() { return allArray; } + @Override public void save() { getStore().setValue(Constants.PREF_COMMANDS_PRESET,PreferenceValueConverter.asCommandDataString(getPresetCommands())); getStore().setValue(Constants.PREF_COMMANDS,PreferenceValueConverter.asCommandDataString(getUserCommands())); } + @Override public void loadDefaults() { getStore().setToDefault(Constants.PREF_COMMANDS_PRESET); getStore().setToDefault(Constants.PREF_COMMANDS); load(); } + @Override public void load() { CommandData[] arrayPreset = PreferenceValueConverter.asCommandDataArray(getStore().getString(Constants.PREF_COMMANDS_PRESET)); CommandData[] arrayUser = PreferenceValueConverter.asCommandDataArray(getStore().getString(Constants.PREF_COMMANDS)); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java index de112267..ca2e046e 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java @@ -89,31 +89,57 @@ public boolean performOk() { } if (save) { CommandDataStore.instance().save(); + MenuDataStore.instance().save(); } return save; } + @Override + protected void performApply() { + performOk(); + } + @Override protected void performDefaults() { + // get the selected commands and referenced menus as lists + List commands = CommandDataStore.instance().getDataList(); + List menus = new ArrayList(); + for(CommandData command : commands) { + if (command.getPresetType() == PresetType.presetUser) { + List menusForOne = MenuDataStore.instance().getRefencedBy(command.getId()); + menus.addAll(menusForOne); + } + } String title = Activator.getResourceString("easyshell.command.page.dialog.defaults.title"); String question = Activator.getResourceString("easyshell.command.page.dialog.defaults.question"); + int dialogImageType = MessageDialog.QUESTION; + if (menus.size() >= 0) { + dialogImageType = MessageDialog.WARNING; + String menuNames = ""; + for (MenuData menu : menus) { + menuNames += menu.getNameExpanded() + "\n"; + } + question = MessageFormat.format(Activator.getResourceString("easyshell.command.page.dialog.defaults.menu.question"), + menuNames); + } MessageDialog dialog = new MessageDialog( null, title, null, question, - MessageDialog.WARNING, + dialogImageType, new String[] {"Yes", "No"}, 1); // no is the default int result = dialog.open(); if (result == 0) { + if (menus.size() >= 0) { + for (MenuData menu : menus) { + MenuDataStore.instance().delete(menu); + } + //MenuDataStore.instance().save(); + } CommandDataStore.instance().loadDefaults(); tableViewer.refresh(); } } - @Override - protected void performApply() { - performOk(); - } - @Override protected Control createContents(Composite parent) { // main page composite @@ -443,8 +469,11 @@ private void removeDialog() { 1); // no is the default int result = dialog.open(); if (result == 0) { - for (MenuData menu : menus) { - MenuDataStore.instance().delete(menu); + if (menus.size() >= 0) { + for (MenuData menu : menus) { + MenuDataStore.instance().delete(menu); + } + //MenuDataStore.instance().save(); } for (CommandData command : commands) { CommandDataStore.instance().delete(command); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/DataStore.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/DataStore.java index 0c0e762e..3f952fda 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/DataStore.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/DataStore.java @@ -158,6 +158,15 @@ public T getByPosition(int position) { return items.get(position); } + public T getById(String id) { + for (T data : getDataList()) { + if (data.getId().equals(id)) { + return data; + } + } + return null; + } + protected IPreferenceStore getStore() { return store; } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java index 8c156810..813c3843 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java @@ -24,28 +24,28 @@ public class MenuData extends Data { private MenuNameType nameType = MenuNameType.menuNameTypeUnknown; private String namePattern = ""; // copy of or reference to command - private CommandData commandData = null; + private String commandId = null; - public MenuData(String id, boolean enabled, MenuNameType nameType, String namePattern, CommandData commandData) { + public MenuData(String id, boolean enabled, MenuNameType nameType, String namePattern, String commandId) { super(id); this.enabled = enabled; this.nameType = nameType; this.namePattern = namePattern; - setCommandData(commandData); + this.commandId = commandId; } - public MenuData(String newId, CommandData commandData) { + public MenuData(String newId, String commandId) { super(newId); setNameType(MenuNameType.menuNameTypeGeneric1); - setCommandData(commandData); + setCommandId(commandId); } - public MenuData(CommandData commandData, boolean generateNewId) { - this(generateNewId ? UUID.randomUUID().toString() : commandData.getId(), commandData); + public MenuData(String commandId, boolean generateNewId) { + this(generateNewId ? UUID.randomUUID().toString() : commandId, commandId); } public MenuData(String newId, MenuData data) { - this(newId, data.getCommandData()); + this(newId, data.getCommandId()); this.enabled = data.isEnabled(); this.nameType = data.getNameType(); this.namePattern = data.getNamePattern(); @@ -79,9 +79,9 @@ public String getNameExpanded() { return expanded; } - public CommandData getCommandData() { - return commandData; - } + public String getCommandId() { + return commandId; + } public boolean equals(Object object) { if(!(object instanceof MenuData)) { @@ -118,34 +118,41 @@ public boolean deserialize(Version version, String value, StringTokenizer tokeni } String namePatternReaded = tokenizer.nextToken(); // ------------------------------------------------- - // set command data members - setCommandData(new CommandData()); - getCommandData().deserialize(version, null, tokenizer, delimiter); - // menu name type handling - if (version.getId() < Version.v2_0_002.getId()) { - // check if readed name is the same, like expanded from patterns - for (MenuNameType type : MenuNameType.getAsList()) { - setNamePattern(type.getPattern()); // set temporary - if (getNameExpanded().equals(namePatternReaded)) { - nameType = type; - break; - } - } + // read new id + if (version.getId() >= Version.v2_0_003.getId()) { + // read the new one + setCommandId(tokenizer.nextToken()); setNameType(nameType); - // if not found set the readed value - if (nameType == MenuNameType.menuNameTypeUser) { - setNamePattern(namePatternReaded); - } - } else if (version.getId() < Version.v2_0_003.getId()) { - setNameType(nameType); - if (nameType == MenuNameType.menuNameTypeUser) { - setNamePattern(namePatternReaded); + setNamePattern(namePatternReaded); + } else { + // read previous command data members + CommandData oldData = new CommandData(); + oldData.deserialize(version, null, tokenizer, delimiter); + setCommandId(oldData.getId()); + // menu name type handling + // set name type and read the old name as pattern and convert to new + if (version.getId() >= Version.v2_0_002.getId()) { + setNameType(nameType); + if (nameType == MenuNameType.menuNameTypeUser) { + setNamePattern(namePatternReaded); + } else { + setNamePattern(nameType.getPattern()); + } } else { - setNamePattern(nameType.getPattern()); + // check if readed name is the same, like expanded from patterns + for (MenuNameType type : MenuNameType.getAsList()) { + setNamePattern(type.getPattern()); // set temporary + if (getNameExpanded().equals(namePatternReaded)) { + nameType = type; + break; + } + } + setNameType(nameType); + // if not found set the readed value + if (nameType == MenuNameType.menuNameTypeUser) { + setNamePattern(namePatternReaded); + } } - } else { - setNameType(nameType); - setNamePattern(namePatternReaded); } return true; } @@ -162,7 +169,11 @@ public String serialize(Version version, String delimiter) { ret += getNameType().toString() + delimiter; } ret += getNamePattern() + delimiter; - ret += commandData.serialize(version, delimiter); + if (version.getId() >= Version.v2_0_003.getId()) { + ret += getCommandId() + delimiter; + } else { + ret += getCommandData().serialize(version, delimiter); + } return ret; } @@ -185,8 +196,12 @@ public void setNamePattern(String namePattern) { this.namePattern = namePattern; } - public void setCommandData(CommandData commandData) { - this.commandData = commandData; + public void setCommandId(String commandId) { + this.commandId = commandId; + } + + public CommandData getCommandData() { + return CommandDataStore.instance().getById(getCommandId()); } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java index 0040e147..9eec6f03 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java @@ -232,7 +232,7 @@ protected void okPressed() { data.setEnabled(enabledCheckBox.getSelection()); data.setNameType(getAllNameTypes()[nameTypeCombo.getSelectionIndex()]); data.setNamePattern(namePatternText.getText()); - data.setCommandData(cmdList.get(commandCombo.getSelectionIndex())); + data.setCommandId(cmdList.get(commandCombo.getSelectionIndex()).getId()); super.okPressed(); } @@ -250,7 +250,7 @@ private void addDialog(CommandData data, boolean copy) { private void addCommand(CommandData data) { CommandDataStore.instance().add(data); - CommandDataStore.instance().save(); + //CommandDataStore.instance().save(); cmdList.add(data); String[] names = getAllCommandsAsComboNames(cmdList); commandCombo.setItems(names); @@ -259,14 +259,14 @@ private void addCommand(CommandData data) { private void replaceCommand(int index, CommandData data) { CommandDataStore.instance().replace(data); - CommandDataStore.instance().save(); + //CommandDataStore.instance().save(); commandCombo.setItem(index, data.getCommandAsComboName()); commandCombo.select(index); } private void removeCommand(int index, CommandData data) { CommandDataStore.instance().delete(data); - CommandDataStore.instance().save(); + //CommandDataStore.instance().save(); //cmdList.remove(data); // no need to search for data, use index instead: cmdList.remove(index); String[] names = getAllCommandsAsComboNames(cmdList); @@ -450,7 +450,7 @@ private void createCommandCombo(Composite parent) { public void widgetSelected(SelectionEvent e) { int index = commandCombo.getSelectionIndex(); //String text = commandCombo.getItem(index); - data.setCommandData(cmdList.get(index)); + data.setCommandId(cmdList.get(index).getId()); commandText.setText(data.getCommandData().getCommand()); boolean isUserDefined = data.getCommandData().getPresetType() == PresetType.presetUser; //editButton.setEnabled(isUserDefined); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java index 9d38cb2b..85ee6967 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java @@ -16,6 +16,8 @@ import java.util.List; import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; import de.anbos.eclipse.easyshell.plugin.Activator; import de.anbos.eclipse.easyshell.plugin.Constants; @@ -33,6 +35,14 @@ public static MenuDataStore instance() { public MenuDataStore(IPreferenceStore store) { super(store); + store.addPropertyChangeListener(new IPropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent event) { + if (event.getProperty().equals(Constants.PREF_MENU)) { + load((String)event.getNewValue()); + } + } + }); } public MenuData[] getCommandMenuDataArray() { @@ -71,17 +81,22 @@ public MenuData[] getEnabledCommandMenuDataArray() { return checked; } + @Override public void save() { getStore().setValue(Constants.PREF_MENU,PreferenceValueConverter.asMenuDataString(getDataList())); } + @Override public void loadDefaults() { getStore().setToDefault(Constants.PREF_MENU); load(); } - public void load() { - MenuData[] items = PreferenceValueConverter.asMenuDataArray(getStore().getString(Constants.PREF_MENU)); + public void load(String prefMenu) { + if (prefMenu == null) { + prefMenu = getStore().getString(Constants.PREF_MENU); + } + MenuData[] items = PreferenceValueConverter.asMenuDataArray(prefMenu); removeAll(); for(int i = 0 ; i < items.length ; i++) { addItem(items[i]); @@ -89,12 +104,17 @@ public void load() { sort(); } + @Override + public void load() { + load(null); + } + public List getRefencedBy(String id) { List ref = new ArrayList(); Iterator dataIterator = getDataList().iterator(); while(dataIterator.hasNext()) { MenuData data = (MenuData)dataIterator.next(); - if(data.getCommandData().getId().equals(id)) { + if(data.getCommandId().equals(id)) { ref.add(data); } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java index f8490a93..934a56b8 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java @@ -89,11 +89,17 @@ public boolean performOk() { } } if (save) { + CommandDataStore.instance().save(); MenuDataStore.instance().save(); } return save; } + @Override + protected void performApply() { + performOk(); + } + @Override protected void performDefaults() { String title = Activator.getResourceString("easyshell.menu.page.dialog.defaults.title"); @@ -110,11 +116,6 @@ protected void performDefaults() { } } - @Override - protected void performApply() { - performOk(); - } - @Override protected Control createContents(Composite parent) { // main page composite @@ -410,7 +411,7 @@ private void addDialog(MenuData data) { } private void addNewDialog() { - MenuData dataNew = new MenuData(commandList.get(0), true); + MenuData dataNew = new MenuData(commandList.get(0).getId(), true); addDialog(dataNew); } From 8d59c5b46da883a9c7b5f177e6e798d8824d3be7 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Tue, 26 Jul 2016 23:11:03 +0200 Subject: [PATCH 35/73] v2.0.0 beta 3 Signed-off-by: Andre Bossert --- .../2.0/2.0.0.v20160726-2110/artifacts.jar | Bin 0 -> 733 bytes .../2.0/2.0.0.v20160726-2110/content.jar | Bin 0 -> 5738 bytes ....easyshell.feature_2.0.0.v20160726-2110.jar | Bin 0 -> 5134 bytes ...e.easyshell.plugin_2.0.0.v20160726-2110.jar | Bin 0 -> 135436 bytes .../updates/testing/2.0/compositeArtifacts.xml | 5 +++-- site/updates/testing/2.0/compositeContent.xml | 5 +++-- 6 files changed, 6 insertions(+), 4 deletions(-) create mode 100644 site/updates/testing/2.0/2.0.0.v20160726-2110/artifacts.jar create mode 100644 site/updates/testing/2.0/2.0.0.v20160726-2110/content.jar create mode 100644 site/updates/testing/2.0/2.0.0.v20160726-2110/features/de.anbos.eclipse.easyshell.feature_2.0.0.v20160726-2110.jar create mode 100644 site/updates/testing/2.0/2.0.0.v20160726-2110/plugins/de.anbos.eclipse.easyshell.plugin_2.0.0.v20160726-2110.jar diff --git a/site/updates/testing/2.0/2.0.0.v20160726-2110/artifacts.jar b/site/updates/testing/2.0/2.0.0.v20160726-2110/artifacts.jar new file mode 100644 index 0000000000000000000000000000000000000000..683d20fa9ed722412a09c65bac529096b59fcd50 GIT binary patch literal 733 zcmWIWW@Zs#;Nak3aNPOJg8>QfGO#ct7L{bCB_@{?>s93D{5!?Ka5n5<-z@`yz2UFy ze>A*$+Mvj|DR!#J+l8yYU0TOgz0Sud<*wDXZ0i!nkMBzxj(8kkx@{X`S($ck&&-Rn z1KAEQpR-spLI*2}Mvs(JE@F?{KgPbcm8+}yoo2A))+SBgH{}7B479)2h=(y< zFTAyz^{nEt`737j%QY68B#9YpDt@{qD4j*<+!RKp{oHC#gaZ{7dW+&tnT7A9(TtT)y2 zIs4i0+@sw+oR{--B6t0|7?GF0N6CJrn(Cw!?)%SG|4jcp_q=gp)2p9?UA@Kq51aJL zT%uM?iBbq&u8x_qpq{^Cvw+bNNo&cdV-4 zxuPj=|MlKDh1JFl|2sEqORjZ|oja|$ei~!*w*Q(1=l2JAvvX8d*hF|TF)-}nU|rIBu=(?P;v01*%vKvF_dU}%sQhHj-h25F=_ z1n&1e-T%GozTUkb&N=Ixwf56_`RQrn;8Fna@$msl&9@qW{~<5{7hvb<;pgDtCj@hM zdl&)$4&+=t7d4VrNtzzV&{(eY$jzSQem5pbJ$o*$nbe>8SuebrNCe9`FCwaJl8x#+ z9?HsE2f28q1O6q`XLO1nEZU5~pi)`LQNXFNS}e zzgxE=3BCLM;jvM&qc-if>uChEd*9Fb9sSJlM{1XWf?;Ah5HS-7j&0{zD?6%c zsgakS^awwAc|m<)OeHf{hOE&8CWrxg3dot{LoWYR{kCcgzT7yk`klj&wQogN?41fO z>d7~Ivr+U+dnIcMwgYlt1IJF(5pV_%ZTvatJlIYCE}YXQ8{!>&d%l}&)7!kRPZ7({ zaeXy^;w|+n_~MW8#cA61iZHX~dtEE}4-c`x)>xunX%_DTqH&#jg!%X0+F)ySS5bO0 z0X$g^(ud0duP?(K^vRx7M%*%8msoWpscnn=3)ra;(^PTG7$YG*4>@;VaEJNWA>aC1 zD208XwO24hbi*+h!(XWMVb)RSLh#MAa%$Uw&m*NPA?W!is#y-JiX@Z_R^O|aWP6`{>CtTDvna~*li&@HP3-ZPoRDY*{cCO)^g zUU4uKW*#kL8qRTaEj6J^;m>%+q_(SG!{z`Wk{7kbS{$%X^f1Y+EBcHZ8`x!xEx+M1 z67$2_G&6-ZR_(PY0HI4B%5ThYWuqp9D?|xCNADZOj3P%d+0`SySfX#>;wl8#yGc~* zE8imDdnyv=P7Axwh?>_Cf#MOHQNXt5#NL+30c0FiH7g51+?_Utw&X=hlJ7SF{>X44 zo}xYN)J21=Y4x+whFgAgt2)bi@B0Cv;SwZm@b@sZdd!JA0Bks9km2A$jEqv?DYD6c zrWDSoC6*dS?{Kg7?`8 zqo~A&r;IRxb4(6+yT)o=_tEVNd94VBbODYi;+!ZMucRj%-WTzEg6j7LbZ+1QdQ?)Y z%J=)!NHP#}-50iwuTQVQ5Rx^ONX!bl33^* z6B2YxlHq^^ORm@w7LA#_`y=4j=$9+Qkt<$P(ecTihx`ZknTS=bXxhRkB5m32Ib|c< zmpjqqWJlG0{6x^+=`R~zKjF#^>yf1M#d+&~OIG*ge%Cjz5f9o=7~#hg|MSd;^z0xv zaV9GZ%LK06`$15E+|S!*j25B_=#J3y-)&+6V$x^DgjU&slf!U}pHU>o2+8*2Dx3t1 z)wb5-e!_<{uH%zq;SZ@UC-2W~_5#yZ?28qcl*Y1x9VNpgt@TN)bC*9mJxoVf=*(v@ zj}$+&(%;|6xjT^2TInD%6k0O^vC8T1X5|qZr0!OrPc84{=ym!mBMp8WR2QG_BC`XJ z?xPdvaW8!1=B0FE%ztT9G=yR+<#6vA-m@vxV#!9lMHiEklgkdW8)0djDXoJ`EP=o~ zHM&%!6a~b^RHJAWv}(jf%4kEzL0Uk`A$C0jm>p|B`_+z63C$mB#-{K7*Ej!Woj<{( zsgEOFRM7l=_IFfPzl6b)Bd=t1{p!TI#|(CUJ+?y?yz|e~0fWnmZ~=AYB#?)OlZS?c zqkvGwnP52vxFLnn=@R|Z94o&A@>T1sNAfpmeRz&pPI)0D0_rX&8VipzE9q=k)w0vX zDxD_x70z*+#O=ZD%PFVXUko)qLd}_%2i7w@M;fr0r50kalb`XuTDZGb$=Ku%_|yhn zA;4h!@V}&X!2JiDFY_~XTX=zU6XkLW&2T<4awwpxG-P4*P4ysm{7K~L{B+;-xw^eg zWE;?;jnXZ7%j%1vGmdZ5uoRpm-koKZrtleoUe~z{uf0v-8}_OIKm{v(ZoTy^`eUIU zF>D0!s+o0V(1bQgYHNmNsCdV}>t#f=9#5}tG;Lt*h*GA}Hu{QhsE#sWAg20ed`yBV zkC;?8j4)wa)Z6zlL^XYzXa;j9$mlYZ9A%R!3?nCK4RgKEmMdoak`dv#fUWpN(zWC{ z+y_~-P)e=SpFd4O$vE*eEpcf6(r*BL@zQZe|NBGKnd#VZgp%|lP7FB;gB<8l56=ur zMEN*Gz65Sy?SwU%s!?f(YbM*BQ0nO`_5)Hx&D>ay=&EIxPfO;QglopSGoLJVwv^N} zxC&xvF60xgZ3;k9yLs%07Z0-Iza5mvd23dPS9#J|q;hi`$WzHaX=@={s z8*&&e@X>QI{TnX&*RU*wzn_ML!mijKk^1(>+bi(Xfxf?1>rhG_$vj7l6u@DE}Al7&3QI5^rUGiz0ul6+QR%kUU^P zpe=lpzA0grGzdjk@<=A|nAg4OC`fgli|;Q9Z*XoVQ1~z|0hXn0!L)uvt%CT=r*oR( zEq5_qehVDHcVLI$k~nMksgG_+wGzLnDKgOpinSW<_KAuP?7;E&^i0wO(BFAfT2xw4 zkY0_yS>=pHw!~1(qVcXcW+`BLE`wKZ1|#L|ltBpBz>9p9QJ_5?msA$e1IIFGr6*&m zbfe}ipHMQ7B3eEi-;V%hI>2~HZ6u2$Mk?O|kTPrq(r*V< zZ!v!pyux|3S6;gyus+eNgT&b6>{Ch-hU$b+HrXS#a^umY@IqrVq7 z)429GYG&sV(j8&B|LKvQ1Xm zpjVg|+|TP_aWQKcnW{A$o19xVt+Vo6#QQAEAye`IDD`gGK@~`rH?5PQvGpYLbx}9q zJ&^}Vg4Gs~`$(}DUy7dCfk7!YFbUw(Qo=t&5sHa35wNGNt2R)h`%8f8*$GcKRO83b zHUlmw1$RNpBK=21Tv2+SMZTZh`jK{X-ANFa>T z;nvEL*m4Sl`a_cbW1<$k?^_Ycf6dd|%85^Ks7~VeiZo*-K2F7dr()|Pl63bhETR&$ zKVu?r3*l?uBc|boy6(wCSe0-3Uh~p7#8Cv)EQymmT{|ZxJAtrPpvLcFEM_xzWksRK zWm;q@^L>7*^oHMc5`2nj2~+94vq}C^H@&%6}8m%Tf<$lj3Ld*_;_Y*k0pGYms(q(wW*}iLLoK6fMI7@Sy>niqp{?sMwCd zQRjX~D+{g2Xr62>mc~y(uvjGuMg<;%wiHxisNHj-|8{<&*xQ)K& zfTp)o|DYsaRWWlk?`3mb#GOpC>)FOT)%FzVt}ES>gN9h$Z}{3@Lk>~_m3>AjwLj(e z+Rb8%(G5L{Ya9Kk{VYETB){NMiCM64&`CBnZgU4^tsN>Sk@vB-mQK>!8HBgi+p8$q zje16|zZ5i!AKv{4OdAM#?dUViIaoIWHd?+dOI}PpbuxEqPXQTy@h=nQJ1mS%Vlgj& zB{s}x7%Xp}%zx=3-s^GU#GQT1m;jvTv0gcv)fdJWlCML5t+_IuoR>c1u1M}uT1St| z-Lz#^kN2qJ!M8xgz()^?>rQycsnfQxq*!d&5fGLs-JY4Xo2>5kZ9Q*$_21w;Jn*a+rg2_gOKt1uZ!>e4vOr5e902W6)=EQAYuEdr|J?05(sbp3|=5)YZFk-JX zD~T`yL5%=WQT58y$CnHB4EGp_EMWAPFNe-V>pD&P@qE^QsCUrVLgd+{Psd6h)lfXTbiu53lf+@j1S8F@pH0n09cr?RO1iy;rH-A z7KA2V2R71x+s9VWt$b!E6AdMCTgNI|+kpSG5R_T5k%V7=&gRMfAHMWFZv;6AiW3le zF?ff6odA`@G8uQaCA<_{IGaBA4cE0c+h$4xXR+L>f8tH$S|50Ma3eK@vSAW8t-i}x{g>Sw`Esf>KozZ z*$z40vy%cz8~HZ>%W-JFU>l0%xFV&)sdMyt>2zv5KTQSC05&t!)1r&bgdu@gI1v?)^_wYyXkb1NAi`y6zUb>q(*EyA2wTs%vwG6Xt9__HVb zP1bgHkOp)N-6-i|QFULLiUlK*#7fY7OMATw`yqmPff0gFENZcn>PcvBVteEw1fZTE z6=c>g=5Top6&XsrQ8CpcQ}EJFL`}%`tl{rPi`xY^miKhWP)L|JyO#(+V>$ap?6-IE zP!CGfDvb+E(Zv<9kSGJplecZlnUlRb!?fDs8DB0p6gpBGE6IZ9km!KQLOSe;C&{{c zi`7c<*(Dk^ldd+(Y}sWgtHtE57H*c^?-L^y-bu81P8(A!j9LTJxX>Na%ghs;IW9s% z`U22It!2o>4{IVJ9$cP5>^kYhMQ!#Lm*`T+3QX@C#MVyOoo^Pn*(Khe5KvOv z(|Y_~VAo=zLX2zvYJ%;TZQYij>Zfw|yZvbAns@Z8;a6`AW)4?c|Dso0k&rm8K||Yo z-K#I;>Gm>J7HzK(gmOZ(PX47RZ|wc!2{Sb!XLf%=v#^G|(gJd<0&P<4)5S{dA()4Q z%k&JH_B#BZhCZeHHI;CMga>o!R$S6gXBU1kYMk?Fi0`nok_B~8nvJzAX~$QsdfEz8 zSmCsX`q<}gMoCX- zWNd6vq4jzjfB9$bw+jzr)X>rsuhQiZUe`LRTl-Zuh+>BtG=O#1oT^Nt?uF_BPB35k zzIWBI*k>+@wb7=Qb&6paj->f7h$e=>GmpbxhCG>w|1Ugq^VkMk`8sRMsx0TuW2?#4 zle}ycJLCaK0u@nhMke2lW$WAe;V`>PHUElTdid+Xwr;@ui+dxX0kN&_d$DOYIU`9b zRcP8}Qnm7-TNA8zPuMYd`p6@~U+C=F;@naZW->iEF!s~b!>_;Dz~e`0sKHIp_RFg# z$QuY@!rXrd)o)X~R7aCdDZEat!Y!>Y`ksF+MYr(awZxPVr&qT-f~!H8nSuV^cGs=O z%lPKzY?p>43U~XuN4Hze!wfEA=aZjR?X%@>Vu$^p(-D)kU3gD((N$ZuXZ!IYg-3OcD4CpjMuITjB~o62hK$ltEG4xiyf8@uz+s@|G$HvVMc|GzbH@+kd(WaUDFoSXy?@9y4R(O0knnZ14W<8Jq;@x%IyiVZJfBj)98=qQux2U!2H+rw|J;8*x|%q+!~g&x0HA=nR0I4YqCdHovY`S{U0X#^ z_m7PlKuAdVe{9tM+O!n3)m4-Y3@ zSQD*nwQ;qkHHDLOhXpI|Zcj6l8oZaAy^KA}j!d0DHF0mKgiGd9n-+ET zPS8W9i&s--TSn8=`C2LzbVOl)nTj{JDDSn2XEL+g9hmdaEW~>* z%U~4yWCVj%ri!>5h*|JRID?w{26DOiswYsCjHZ2DugD=NiW9R0Pn2i9T|uHs6rn87 zMs38KAze!z<;qXs+4CLKvhVcSya;hfQKFeclRi)DLXuy%;N&u|e^`uE=nQb7BCv^8 z+V!QLRG#f7nH?EDLy~$dX$Qbzfy9#P1CY8n^ECk5NNb$JrkZId$lTO{4cHKNMRWd( zer_OCmNr<+Y6sX_t5k)cpzJ}QcwV{IFVi*=Z8%o_a>%j6p@I zUTYomletkH^k^oRQ0K|olRJO=^!(FCtQ41&197dlV|5&;)1mH@C{#K`8SLc{i#Mv@ zDa)#8(B6H{S-wE;9oHAy0CmYgX?Is>Ltel~DJ=Oo;1+Hyj$S-nqoWo$n4+4QBQq=Wpo+&<)d`u1m=To*XiX+DR+MAZ*v`5)K1P6GsMT#eRlk zfg!s@rdi_g!wYD|9iI4S`%wq!{Zt3hM%8CI&1MfhK5;OOifR_zx)45#hIJt2=rCrq zI*GQ)%VAY7)_%D1zb1PStGSFY=j)1dt$M{3Gb?}v5NyHq8EeJ7wZk32mG%KK>w zU_8brUL~S$Wr0a6+0o;5I3YR>%0SBmKVw2Tam}{E+^i>f2u*r(?=H;9&e&+hti)fm zm%tamiEAs*OJ(lhbpYb2C<)vHFZz1nQ_E@*h-5*dj+H&Jzoi-UrB7P8tyZSL#G<0z zHD6j2=r7QBOfDDQY_NlL#4k?+V6n9s2&vwC$;-h{vQjZwd2F)Y8BK&D7}l#_>N?C{ z{8p*Mar7ffgiQ+vQprFv@8yh3m)&F-KV{D?RUj%^fkRFyP4X-f<*ILV*w5kyM4HzY zs{zp?w79U}=aa*1zN;CcgDZ%EmOFe@l}8_=>_Hkw-w&-Z%s9)c z8~!2nAO#6Z2r4tArOiYyWD40hlTfOtr-m_2wL7f;_+GDfiO$-OHik<6Y|-LZ442O| z#1!lDX{`^K-pWSe!Q0oJzEL>r-x%iXHmrIYK-y|MgzHER2*G*LG*{$fxt@F5cad&E zdNUd1yRw~C9IfII)$*IwAMRZYo|@((tKmg=#OCt zH2ie<-IBRigV2}BBA7i!Le{2hHdZb|bctZD+i5JDedK+(op04dYLw$qRb)V$p<-N5 z(PWfF)mIL$aooT!aj{jF-}F8Z4VZTjrOp$t(e_{!jcS8tdhCo6>&k_-rQ@kgG75)f zsWv=zANiP3ujl^xc?O{L9=2!K?v~;@JD|A0JdH5vrd>;r5Kvz0W$laP=m?oLO_>if~3uI^mRB1QYW6YrRU3@Ljz63kH3`IXVzV#=SuG-?2g`!%>F%X>a4I1qROpx|C~m-B z9A@3R4$^`jxo)kUlHR6D2}TchRIrH9d`>U&LUB6Q@+F(Rdv}d{M8CxVX1|$}i&V;@c*8EHie*OB%-=j-@R^DMdFq8ZQ3rffK~&W{gl(erVEG zstYN=?Pk`7hY{0-ArXUSe%JmwSdxez?Qa)UXz?U#Z%kUYcB5$+(=kr$6FpO#J@sm& zoOI}NPjOo>uR|;>>k^U&RWkH%NPmi=MG5CfgFe37dey&hNS_|m1-;)56f< z-#-6<=eXHfUu%4#;VpBTKZ6W=_KHkJ#G>U0pqnG$-ZlE}bZMS_!V`gVG{|>v;NRsYBCmK0Jy@ngbSs10BdOaPyzgmis^0 z>f~dZ_{wCny6EiMKmBo7#mlX$%=~G3g#&|GyrJlRg21Y{Xl$-0Na&TqI zu?OOv_3QSAjGtd~b=7_XB^;-Oy zC}|&IPnh$PxR>s{JAL?g%xykRa^G-Kh0`9kYf=!tj!SBa01l??+Z0m@!m5dEx* zEDuz=r@Tp-cFX%(QQo_@!XMv@+*5GJ$JkZ6HgLho)q||)%eUcna_%T8#hXtr9V3REH^o|S=F5s{)l0i z`#A+nBQ?m$W{do zF?PUw2%s>p0^mVLrO3UZqp_9PL$g?0>b63W{oaAO@y2K&w7%P_bFE zKC`s5`!bR-X};xLIBODo!AA#f8^>h7X1x>-6_+O)mLqMIRZ|5OAl|x$vt=Zg&inKUyS?B%$>crga4m{i$kIEjQz2nQXgekq8 z9$%_e;#>b3w@AO(Rg2kMhsaz_A(~{KQe5vvXE-H_$UvfRENJe{zVzLYXAFYJ zEg^7?>wZ+QjbD+gwqhM^RrQ)hzbagCh>t%CRhqI<8~7Wx^ewG4WA8gQHj9KR+HDZV zkpekm^T4iVEzYy>4*1SIiqcwWCQrOQwt_&^ISZHp0R&uW%>e_lctv5>vOfNXzUm5w z!lr|W;_i7Eo86+=q}Ey}72`$`vmOLedr~^8dfkaB54F#Gsj`K{ zmrTWt-qCjSa{aDk->z3bu2khm%h~uzT;N8^xqrWlKTBG?a!|k`>eU)iMQ`0|9y46) zaKVY#oQ3@rF4OJKBW~-8Szk_Sb)glh_*Y&^7M0tK zH0`nH;7<(sP~#|800)bYaWudD9P8)-Xi7hs$WTq~@(~Gx+vB;2*FRm+t+Ye5xwOoz zppTYAg*2GKm**p}{V_&s{0V_$TS*O^gB{^o_Ic6`>+vC%(sq)o*t%qQ$;6r;!ql_P zN0DXGM(29av_kLl4Nmr38XG4 z85&dA=E>L8y5ZHzIBezBPcoD(_vCsp5KSCt>xeZByl_kLoLrLhf#_?x3Q|s-_n!JQ zqY90D;6v8xqTkgS>AnXnwzs=ZjaY|?vF;iUkXDYuC99cjf3F4fNB-^yT3gwU0j{ZW z)?_5yrEFeyFOZW*nb1aZ9z2N8tfP2nWiS2y4xJV-hKOu);a1*aUYa|S#qDGKWE?SzHicUI#b8Os^Vwm7xNDJ7#7h8Nnu zFmfjQd2o#N4=4i2X#LA#dD+arAyhao=e!J;Jx=zhS6_d~Wb|Vva!vk)_vY2sYtGCA)H;>PYV z1^w#h{dH&$Le@ZZC1qs=mXTiw*74ZKt@;Np%3Df)#vY|aE9n(kEG^swzuD7C*%lps zau)`gW^sl};M5inp+E7-Ug!F43++|>Kn^T2j_hXxje(u{Eb*#WGA|Of!_JB?&amvy zVz4an+o&6NOD0@>`(qC7K;QNSf!n7sH=NNchog}`wzK*8f)1OX`!usG>2Fqkc4D&I znn~M=j_9Q3BQFMb4hHkD^zd&*yN!@5ayg$Jyr@b1j(*-0T^$n0-H`v~O$w`=8WNNM zfR*rH-h_osjr0F=v_H`4kM0BZ6#mA4sM_DQ|K)1`BCNk$?LR7f!SyHopSFJ}+kZd& mzc>6l)L+!~9~His`IG(wzH~M5@c$NZ{;ZlmQHAR7>AwJ-2BoY3 literal 0 HcmV?d00001 diff --git a/site/updates/testing/2.0/2.0.0.v20160726-2110/plugins/de.anbos.eclipse.easyshell.plugin_2.0.0.v20160726-2110.jar b/site/updates/testing/2.0/2.0.0.v20160726-2110/plugins/de.anbos.eclipse.easyshell.plugin_2.0.0.v20160726-2110.jar new file mode 100644 index 0000000000000000000000000000000000000000..e2947a1d92a9bb0fe9ccf56b75675361d24ef2c1 GIT binary patch literal 135436 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 - + - + + diff --git a/site/updates/testing/2.0/compositeContent.xml b/site/updates/testing/2.0/compositeContent.xml index 3c75b324..81e2d797 100644 --- a/site/updates/testing/2.0/compositeContent.xml +++ b/site/updates/testing/2.0/compositeContent.xml @@ -2,10 +2,11 @@ - + - + + From cafa724e2c0b934bdec80520d461e0b4338ff7d9 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Tue, 26 Jul 2016 23:34:11 +0200 Subject: [PATCH 36/73] fixed missing commandDataStore during menu creation Signed-off-by: Andre Bossert --- .../plugin/commands/DefineCommands.java | 2 ++ .../2.0/2.0.0.v20160726-2133/artifacts.jar | Bin 0 -> 733 bytes .../2.0/2.0.0.v20160726-2133/content.jar | Bin 0 -> 5771 bytes ....easyshell.feature_2.0.0.v20160726-2133.jar | Bin 0 -> 5134 bytes ...e.easyshell.plugin_2.0.0.v20160726-2133.jar | Bin 0 -> 135463 bytes .../updates/testing/2.0/compositeArtifacts.xml | 5 +++-- site/updates/testing/2.0/compositeContent.xml | 5 +++-- 7 files changed, 8 insertions(+), 4 deletions(-) create mode 100644 site/updates/testing/2.0/2.0.0.v20160726-2133/artifacts.jar create mode 100644 site/updates/testing/2.0/2.0.0.v20160726-2133/content.jar create mode 100644 site/updates/testing/2.0/2.0.0.v20160726-2133/features/de.anbos.eclipse.easyshell.feature_2.0.0.v20160726-2133.jar create mode 100644 site/updates/testing/2.0/2.0.0.v20160726-2133/plugins/de.anbos.eclipse.easyshell.plugin_2.0.0.v20160726-2133.jar diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java index 95147dfc..4abf8363 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java @@ -23,6 +23,7 @@ import org.eclipse.ui.services.IServiceLocator; import de.anbos.eclipse.easyshell.plugin.Activator; +import de.anbos.eclipse.easyshell.plugin.preferences.CommandDataStore; import de.anbos.eclipse.easyshell.plugin.preferences.MenuData; import de.anbos.eclipse.easyshell.plugin.preferences.MenuDataStore; @@ -36,6 +37,7 @@ public void createContributionItems(IServiceLocator serviceLocator, IContributionRoot additions) { // load the preferences + CommandDataStore.instance().load(); MenuDataStore.instance().load(); List items = MenuDataStore.instance().getEnabledCommandMenuDataList(); for (MenuData item : items) { diff --git a/site/updates/testing/2.0/2.0.0.v20160726-2133/artifacts.jar b/site/updates/testing/2.0/2.0.0.v20160726-2133/artifacts.jar new file mode 100644 index 0000000000000000000000000000000000000000..0ce5b9426d258864ba4f3a8c53ac061ecb4f85a7 GIT binary patch literal 733 zcmWIWW@Zs#;Nak3Fx>OYg8>QfGO#ct7L{bCB_@{?>s93D{5!?Ka5n5<-z@`yz2UFy ze>7xSByb3Lg$8YDUw7+tS?G=8)Jcl3uWgLIy^y=3em%2_8&v&Z1uk1tjiqkCU$7)G?A1}bH4J%= zwv=f+~nA%8~f|swTH2(rhSJu@$@X6S=6a}=v*GFQ8&XEALIn4|)>^ack|n!I z@|~u>g1>XKpDC|8K1b?s+L@b6JSAs7Q+jy8;p@yRl3OPhr8->7NKh$WT_pYR)~Xqw zo1eX&_NekyOXk%uoyh+y)|MH^O`abznaT6g()XXG{=NRG_k5<24 z7u)~)lv{MOBS}+-!@5v?@2ST}jzs#bJ$*N7(_cRRchQMjx2xk){>_;adiC3eKg}x+ zy>=BXIUKkDH&bLR!yo^atpCou#1C% mA;6oFNrVBB5|QOVDG?Q5q{{$rRyL3lMj*5Y(j7o!85jV=p;7q& literal 0 HcmV?d00001 diff --git a/site/updates/testing/2.0/2.0.0.v20160726-2133/content.jar b/site/updates/testing/2.0/2.0.0.v20160726-2133/content.jar new file mode 100644 index 0000000000000000000000000000000000000000..ee83d9f56be9be67b131ede391b6505a410ade16 GIT binary patch literal 5771 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 O{*$u*R7vW8vHt*{Y#-DB literal 0 HcmV?d00001 diff --git a/site/updates/testing/2.0/2.0.0.v20160726-2133/features/de.anbos.eclipse.easyshell.feature_2.0.0.v20160726-2133.jar b/site/updates/testing/2.0/2.0.0.v20160726-2133/features/de.anbos.eclipse.easyshell.feature_2.0.0.v20160726-2133.jar new file mode 100644 index 0000000000000000000000000000000000000000..6c85b4d70ca81551751130a6aa5114e5c561954b GIT binary patch literal 5134 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 literal 0 HcmV?d00001 diff --git a/site/updates/testing/2.0/2.0.0.v20160726-2133/plugins/de.anbos.eclipse.easyshell.plugin_2.0.0.v20160726-2133.jar b/site/updates/testing/2.0/2.0.0.v20160726-2133/plugins/de.anbos.eclipse.easyshell.plugin_2.0.0.v20160726-2133.jar new file mode 100644 index 0000000000000000000000000000000000000000..e7e199cb0f65e67225a5604f79f9b16ff6065bdc GIT binary patch literal 135463 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 literal 0 HcmV?d00001 diff --git a/site/updates/testing/2.0/compositeArtifacts.xml b/site/updates/testing/2.0/compositeArtifacts.xml index 24a8ddee..a80a617e 100644 --- a/site/updates/testing/2.0/compositeArtifacts.xml +++ b/site/updates/testing/2.0/compositeArtifacts.xml @@ -2,11 +2,12 @@ - + - + + diff --git a/site/updates/testing/2.0/compositeContent.xml b/site/updates/testing/2.0/compositeContent.xml index 81e2d797..33debdd6 100644 --- a/site/updates/testing/2.0/compositeContent.xml +++ b/site/updates/testing/2.0/compositeContent.xml @@ -2,11 +2,12 @@ - + - + + From 7e9d598b8141c01a102f4ae69d0c34f52d598a71 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Sun, 31 Jul 2016 00:00:06 +0200 Subject: [PATCH 37/73] refactoring of argument handling - added: #16 Copy Fully Qualified Class Name Signed-off-by: Andre Bossert --- .../org.eclipse.core.resources.prefs | 2 + .../org.eclipse.core.resources.prefs | 2 + plugin/META-INF/MANIFEST.MF | 3 +- .../plugin/DynamicVariableResolver.java | 57 ++++++-- .../eclipse/easyshell/plugin/Resource.java | 131 +++++++++++++++++- .../easyshell/plugin/ResourceUtils.java | 26 ++-- .../plugin/actions/ActionDelegate.java | 94 ++----------- .../CommandDataDefaultCollection.java | 21 +-- uuids.txt | 10 +- 9 files changed, 219 insertions(+), 127 deletions(-) create mode 100644 feature/.settings/org.eclipse.core.resources.prefs create mode 100644 plugin/.settings/org.eclipse.core.resources.prefs diff --git a/feature/.settings/org.eclipse.core.resources.prefs b/feature/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 00000000..99f26c02 --- /dev/null +++ b/feature/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/plugin/.settings/org.eclipse.core.resources.prefs b/plugin/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 00000000..99f26c02 --- /dev/null +++ b/plugin/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/plugin/META-INF/MANIFEST.MF b/plugin/META-INF/MANIFEST.MF index d59cf01c..6a3468bd 100644 --- a/plugin/META-INF/MANIFEST.MF +++ b/plugin/META-INF/MANIFEST.MF @@ -9,7 +9,8 @@ Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime, org.eclipse.core.resources, org.eclipse.core.expressions, - org.eclipse.core.variables + org.eclipse.core.variables, + org.eclipse.jdt.core;resolution:=optional Bundle-RequiredExecutionEnvironment: JavaSE-1.7 Bundle-ActivationPolicy: lazy Bundle-ClassPath: target/easyshell-library.jar diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/DynamicVariableResolver.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/DynamicVariableResolver.java index f9d289fd..9c6ebcee 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/DynamicVariableResolver.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/DynamicVariableResolver.java @@ -15,9 +15,12 @@ import org.eclipse.core.variables.IDynamicVariable; import org.eclipse.core.variables.IDynamicVariableResolver; +import de.anbos.eclipse.easyshell.plugin.types.Quotes; + public class DynamicVariableResolver implements IDynamicVariableResolver { - private static String[] args = new String[6]; + static private Resource resource = null; + static Quotes quotes = Quotes.quotesNo; @Override public String resolveValue(IDynamicVariable variable, String argument) @@ -33,9 +36,9 @@ public String resolveValue(IDynamicVariable variable, String argument) private String handleOwnVariable(String argument) { if (argument.equals("drive")) { - return args[0]; + return resource.getWindowsDrive(); // {0} == ${easyshell:drive} } else if (argument.equals("line_separator")) { - return args[5]; + return resource.getLineSeparator(); // {5} == ${easyshell:line_separator} } // here we have eclipse variables embedded in easyshell variable as parameter return handleEclipseVariable(argument, null); @@ -43,23 +46,51 @@ private String handleOwnVariable(String argument) { private String handleEclipseVariable(String variable, String argument) { if (variable.equals("container_loc")) { - return args[1]; + return autoQuotes(resource.getParentPath()); // {1} == ${easyshell:container_loc} } else if (variable.equals("resource_loc")) { - return args[2]; + return autoQuotes(resource.getFullPath()); // {2} == ${easyshell:resource_loc} } else if (variable.equals("resource_name")) { - return args[3]; + return autoQuotes(resource.getFileName()); // {3} == ${easyshell:resource_name} } else if (variable.equals("project_name")) { - return args[4]; + return resource.getProjectName(); // {4} == ${easyshell:project_name} + } else if (variable.equals("qualified_name")) { + return resource.getFullQualifiedName(); // {6} == ${easyshell:qualified_name} == qualified name } return null; } - public String[] getArgs() { - return args; - } + public static Resource getResource() { + return resource; + } - public static void setArgs(String[] args) { - DynamicVariableResolver.args = args; - } + public static void setResource(Resource resource) { + DynamicVariableResolver.resource = resource; + } + + public static void setQuotes(Quotes quotes) { + DynamicVariableResolver.quotes = quotes; + } + + private String autoQuotes(String str) { + String ret = str; + if (quotes == Quotes.quotesSingle) { + ret = "'" + str + "'"; + } + else if (quotes == Quotes.quotesDouble) { + ret = "\"" + str + "\""; + } + else if (quotes == Quotes.quotesEscape) { + ret = str.replaceAll("\\s", "\\\\ "); + } + else if ( ((quotes == Quotes.quotesAuto) || (quotes == Quotes.quotesAutoSingle)) + && (str.indexOf(" ") != -1) ) { // if space there + if ((quotes == Quotes.quotesAutoSingle) && str.indexOf("\"") == -1) { // if no single quotes + ret = "'" + str + "'"; + } else if (str.indexOf("'") == -1){ // if no double quotes + ret = "\"" + str + "\""; + } + } + return ret; + } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/Resource.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/Resource.java index 8d1aeef1..0bb2f6db 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/Resource.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/Resource.java @@ -13,27 +13,152 @@ import java.io.File; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jdt.core.IPackageFragment; +import org.eclipse.jdt.core.JavaCore; +import org.osgi.framework.Bundle; + public class Resource { + // internal private File file = null; + private IResource iRes = null; + + // resolved + private String windowsDrive = null; + private String fullPath = null; + private String parentPath = null; + private String fileName = null; private String projectName = null; + static private String lineSeparator = null; + + //Activator.logDebug("full_path : >" + fullPath + "<"); + //Activator.logDebug("parent_path: >" + parentPath + "<"); + //Activator.logDebug("file_name : >" + fileName + "<"); public Resource(Resource myRes) { file = myRes.getFile(); projectName = myRes.getProjectName(); } - public Resource(File myFile, String myProjectName) { - file = myFile; - projectName = myProjectName; + public Resource(File file, IResource iRes, String projectName) { + this.file = file; + this.iRes = iRes; + this.projectName = projectName; + } + + public Resource(File file, String projectName) { + this(file, null, projectName); + } + + public Resource(IResource iRes) { + this(iRes.getLocation().toFile(), iRes, iRes.getProject().getName()); } public File getFile() { return file; } + public IResource getIResource() { + return iRes; + } + + public String getWindowsDrive() { + if (windowsDrive == null) { + getFullPath(); + // Try to extract drive on Win32 + if (fullPath.indexOf(":") != -1) { + windowsDrive = fullPath.substring(0, fullPath.indexOf(":")); + } else { + windowsDrive = ""; + } + } + return windowsDrive; + } + + public String getFullPath() { + if (fullPath == null) { + fullPath = file.toString(); + } + return fullPath; + } + + public String getParentPath() { + if (parentPath == null) { + if (file.isDirectory()) { + parentPath = getFile().getPath(); + } else { + parentPath = file.getParent(); + fileName = file.getName(); + } + } + return parentPath; + } + + public String getParentName() { + if (iRes != null) { + return iRes.getParent().getName(); + } + return file.getParentFile().getName(); + } + + public String getFileName() { + if (fileName == null) { + if (file.isDirectory()) { + fileName = ""; + } else { + fileName = file.getName(); + } + } + return fileName; + } + public String getProjectName() { return projectName; } + public String getLineSeparator() { + if (lineSeparator == null) { + lineSeparator = System.getProperty("line.separator"); + } + return lineSeparator; + } + + public String getFullQualifiedName() { + if (iRes != null) { + Bundle bundle = Platform.getBundle("org.eclipse.jdt.core"); + if (bundle != null) { + IJavaElement element = JavaCore.create(iRes); + if (element instanceof IPackageFragment) { + return ((IPackageFragment)element).getElementName(); + } else if (element instanceof ICompilationUnit) { + return ((ICompilationUnit)element).findPrimaryType().getFullyQualifiedName(); + } + } + } + return getFullQualifiedPathName(); + } + + public String getFullQualifiedPathName() { + String fqcn = ""; + if (iRes != null) { + return iRes.getFullPath().toString(); + /* + String[] segments = iRes.getProjectRelativePath().segments(); + for (int i=0;i"); cmdAll += cmd; Activator.logDebug(cmd); @@ -105,7 +105,7 @@ public void run(IAction action) { } // handling command line else { - handleExec(variableManager, quotes); + handleExec(variableManager); } } catch (CoreException e) { Activator.logError(Activator.getResourceString("easyshell.message.error.validation"), commandValue, e, true); @@ -123,46 +123,7 @@ public void run(IAction action) { } } - private String[] fillArguments(Resource res, IStringVariableManager variableManager, Quotes quotes) { - String[] args = null; - String drive = null; - String full_path = null; - String parent_path = null; - String file_name = null; - full_path = res.getFile().toString(); - if (res.getFile().isDirectory()) { - parent_path = res.getFile().getPath(); - //file_name = "dir"; // dummy cmd - } else { - parent_path = res.getFile().getParent(); - file_name = res.getFile().getName(); - } - if (full_path != null) { - Activator.logDebug("full_path : >" + full_path + "<"); - Activator.logDebug("parent_path: >" + parent_path + "<"); - Activator.logDebug("file_name : >" + file_name + "<"); - // Try to extract drive on Win32 - if (full_path.indexOf(":") != -1) { - drive = full_path.substring(0, full_path.indexOf(":")); - } - String project_name = res.getProjectName(); - if (project_name == null || project_name.isEmpty()) { - project_name = Activator.getResourceString("easyshell.plugin.name"); - } - String line_separator = System.getProperty("line.separator"); - // args format - args = new String[6]; - args[0] = drive; // {0} == ${easyshell:drive} - args[1] = autoQuotes(parent_path, quotes); // {1} == ${easyshell:container_loc} - args[2] = autoQuotes(full_path, quotes); // {2} == ${easyshell:resource_loc} - args[3] = autoQuotes(file_name, quotes); // {3} == ${easyshell:resource_name} - args[4] = project_name; // {4} == ${easyshell:project_name} - args[5] = line_separator; // {5} == ${easyshell:line_separator} - } - return args; - } - - private void handleExec(IStringVariableManager variableManager, Quotes quotes) throws CoreException, IOException { + private void handleExec(IStringVariableManager variableManager) throws CoreException, IOException { String[] cmds = null; // working directory if (commandWorkingDir != null && !commandWorkingDir.isEmpty()) { @@ -179,14 +140,14 @@ private void handleExec(IStringVariableManager variableManager, Quotes quotes) t cmds = new String[st.countTokens()]; int i = 0; while (st.hasMoreElements()) { - cmds[i] = fixQuotes(variableManager.performStringSubstitution(st.nextToken(), false), quotes); + cmds[i] = variableManager.performStringSubstitution(st.nextToken(), false); i++; } } // the old command line passing without string tokenizer else { cmds = new String[1]; - cmds[0] = fixQuotes(variableManager.performStringSubstitution(commandValue, false), quotes); + cmds[0] = variableManager.performStringSubstitution(commandValue, false); } // log out for (int i=0;i= 1) { resource = new Resource[selectedObjects.length]; for (int i=0;i getCommandsNativeAsMenu(boolean sorted) { addWindowsCommands(); addLinuxCommands(); addMacOSXCommands(); + addAllOSCommands(); } @@ -99,8 +100,8 @@ private void addWindowsCommands() { // Windows TotalCommander list.add(new CommandData("e487327c-dfdb-42e7-bf16-3b81a34e5703", PresetType.presetPlugin, OS.osWindows, "TotalCommander", ResourceType.resourceTypeFileOrDirectory, Category.categoryExplore, CommandType.commandTypeExecute, "cmd.exe /C totalcmd64.exe /O /T ${easyshell:container_loc}")); - // Windows Clipboard - list.add(new CommandData("67aa9dff-6bbb-4b47-8b43-8a82a7a279fa", PresetType.presetPlugin, OS.osWindows, "Full path", ResourceType.resourceTypeFileOrDirectory, Category.categoryClipboard, CommandType.commandTypeClipboard, + // Windows Clipboard - Full Path + list.add(new CommandData("67aa9dff-6bbb-4b47-8b43-8a82a7a279fa", PresetType.presetPlugin, OS.osWindows, "Full Path", ResourceType.resourceTypeFileOrDirectory, Category.categoryClipboard, CommandType.commandTypeClipboard, "\"${easyshell:resource_loc}\"${easyshell:line_separator}")); } @@ -159,9 +160,6 @@ private void addLinuxCommands() { // Linux Thunar list.add(new CommandData("cf8d4d60-10f4-4a31-a423-676d02d974e0", PresetType.presetPlugin, OS.osLinux, "Thunar", ResourceType.resourceTypeFileOrDirectory, Category.categoryExplore, CommandType.commandTypeExecute, "thunar ${easyshell:container_loc}")); - // Linux Clipboard - list.add(new CommandData("33043fe3-1a5f-46d7-b94e-9a02ef204e7d", PresetType.presetPlugin, OS.osLinux, "Full path", ResourceType.resourceTypeFileOrDirectory, Category.categoryClipboard, CommandType.commandTypeClipboard, - "${easyshell:resource_loc}${easyshell:line_separator}")); } private void addMacOSXCommands() { @@ -173,9 +171,15 @@ private void addMacOSXCommands() { // MAC OS X Finder list.add(new CommandData("f6bcdd71-4687-46d8-bf34-2780bafd762a", PresetType.presetPlugin, OS.osMacOSX, "Finder", ResourceType.resourceTypeFileOrDirectory, Category.categoryExplore, CommandType.commandTypeExecute, "open -R ${easyshell:resource_loc}")); - // MAC OS X Clipboard - list.add(new CommandData("cd32fa5a-34d7-4551-8bd0-3aae0dc444d0", PresetType.presetPlugin, OS.osMacOSX, "Full path", ResourceType.resourceTypeFileOrDirectory, Category.categoryClipboard, CommandType.commandTypeClipboard, + } + + private void addAllOSCommands() { + // Clipboard - Full Path + list.add(new CommandData("33043fe3-1a5f-46d7-b94e-9a02ef204e7d", PresetType.presetPlugin, OS.osLinux, "Full Path", ResourceType.resourceTypeFileOrDirectory, Category.categoryClipboard, CommandType.commandTypeClipboard, "${easyshell:resource_loc}${easyshell:line_separator}")); + // Clipboard - Qualified name + list.add(new CommandData("88989d78-cf17-4750-91fc-6260055743ae", PresetType.presetPlugin, Utils.getOS(), "Qualified Name", ResourceType.resourceTypeFileOrDirectory, Category.categoryClipboard, CommandType.commandTypeClipboard, + "${easyshell:qualified_name}${easyshell:line_separator}")); } public List getCommands() { @@ -252,7 +256,8 @@ private static List getDefaultCommands() { break; } // add clipboard - addNotNull(listDefault, getCommandData(listOS, ".*path", Category.categoryClipboard)); + addNotNull(listDefault, getCommandData(listOS, ".*Path", Category.categoryClipboard)); + addNotNull(listDefault, getCommandData(listOS, ".*Name", Category.categoryClipboard)); return listDefault; } diff --git a/uuids.txt b/uuids.txt index 7afc7146..2debd189 100644 --- a/uuids.txt +++ b/uuids.txt @@ -40,16 +40,20 @@ cb9a8c00-89bc-453c-aeff-ae94c0d9e44a 4fbfa632-5455-4384-9f9e-773603a12bea 8e14d26d-2981-4b81-b8e5-6a942c6f2c59 cf8d4d60-10f4-4a31-a423-676d02d974e0 -33043fe3-1a5f-46d7-b94e-9a02ef204e7d MacOSX e6918fe0-38b8-450b-a4be-d9eecc0dc0b4 db61d61e-8bf4-41d0-a1d8-00379e4d1db1 f6bcdd71-4687-46d8-bf34-2780bafd762a -cd32fa5a-34d7-4551-8bd0-3aae0dc444d0 -Free +All +33043fe3-1a5f-46d7-b94e-9a02ef204e7d 88989d78-cf17-4750-91fc-6260055743ae + +Do not use +cd32fa5a-34d7-4551-8bd0-3aae0dc444d0 // was MAC OS X clipboard before + +Free e6de32cc-342a-46a0-a766-ac74e7e4000d d2726c3f-6da3-46b5-8029-1c63d0ff6bd2 03e6678b-f67f-42ed-b65f-6b6f06ec0e8f From a7365a8a2f17b640e61bb71d27bec17cb3d4eaa5 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Sun, 31 Jul 2016 16:42:50 +0200 Subject: [PATCH 38/73] #72 [v2.0] add *_path eclipse variables added new variables: ${easyshell:resource_path} ${easyshell:container_name} ${easyshell:container_path} ${easyshell:project_loc} ${easyshell:project_path} renamed ${easyshell:drive} to ${easyshell:windows_drive} Signed-off-by: Andre Bossert --- .../plugin/DynamicVariableResolver.java | 30 ++-- .../eclipse/easyshell/plugin/Resource.java | 142 ++++++++++++------ .../easyshell/plugin/ResourceUtils.java | 8 +- .../plugin/actions/ActionDelegate.java | 3 +- .../CommandDataDefaultCollection.java | 3 + .../plugin/preferences/CommandDataDialog.java | 17 ++- uuids.txt | 2 +- 7 files changed, 136 insertions(+), 69 deletions(-) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/DynamicVariableResolver.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/DynamicVariableResolver.java index 9c6ebcee..18f4d6f7 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/DynamicVariableResolver.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/DynamicVariableResolver.java @@ -35,26 +35,36 @@ public String resolveValue(IDynamicVariable variable, String argument) } private String handleOwnVariable(String argument) { - if (argument.equals("drive")) { - return resource.getWindowsDrive(); // {0} == ${easyshell:drive} + if (argument.equals("windows_drive")) { + return resource.getWindowsDrive(); // ${easyshell:windows_drive} == {0} } else if (argument.equals("line_separator")) { - return resource.getLineSeparator(); // {5} == ${easyshell:line_separator} + return resource.getLineSeparator(); // ${easyshell:line_separator} == {5} + } else if (argument.equals("qualified_name")) { + return resource.getFullQualifiedName(); // ${easyshell:qualified_name} } - // here we have eclipse variables embedded in easyshell variable as parameter + // here we have a eclipse variable embedded in easyshell variable as parameter return handleEclipseVariable(argument, null); } private String handleEclipseVariable(String variable, String argument) { if (variable.equals("container_loc")) { - return autoQuotes(resource.getParentPath()); // {1} == ${easyshell:container_loc} + return autoQuotes(resource.getContainerLocation()); // ${easyshell:container_loc} == {1} + } else if (variable.equals("container_name")) { + return autoQuotes(resource.getContainerName()); // ${easyshell:container_name} + } else if (variable.equals("container_path")) { + return autoQuotes(resource.getContainerPath()); // ${easyshell:container_path} } else if (variable.equals("resource_loc")) { - return autoQuotes(resource.getFullPath()); // {2} == ${easyshell:resource_loc} + return autoQuotes(resource.getResourceLocation()); // ${easyshell:resource_loc} == {2} } else if (variable.equals("resource_name")) { - return autoQuotes(resource.getFileName()); // {3} == ${easyshell:resource_name} + return autoQuotes(resource.getResourceName()); // ${easyshell:resource_name} == {3} + } else if (variable.equals("resource_path")) { + return autoQuotes(resource.getResourcePath()); // ${easyshell:resource_path} + } else if (variable.equals("project_loc")) { + return autoQuotes(resource.getProjectLocation()); // ${easyshell:project_loc_loc} } else if (variable.equals("project_name")) { - return resource.getProjectName(); // {4} == ${easyshell:project_name} - } else if (variable.equals("qualified_name")) { - return resource.getFullQualifiedName(); // {6} == ${easyshell:qualified_name} == qualified name + return resource.getProjectName(); // ${easyshell:project_name} == {4} + } else if (variable.equals("project_path")) { + return autoQuotes(resource.getProjectPath()); // ${easyshell:project_path} } return null; } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/Resource.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/Resource.java index 0bb2f6db..6e4d1f88 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/Resource.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/Resource.java @@ -18,6 +18,7 @@ import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IPackageFragment; +import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaCore; import org.osgi.framework.Bundle; @@ -25,14 +26,14 @@ public class Resource { // internal private File file = null; - private IResource iRes = null; + private IResource resource = null; // resolved private String windowsDrive = null; - private String fullPath = null; - private String parentPath = null; - private String fileName = null; - private String projectName = null; + private String resourceLocation = null; + private String containerLocation = null; + private String resourceName = null; + private String projectName = Activator.getResourceString("easyshell.plugin.name"); static private String lineSeparator = null; //Activator.logDebug("full_path : >" + fullPath + "<"); @@ -41,37 +42,35 @@ public class Resource { public Resource(Resource myRes) { file = myRes.getFile(); - projectName = myRes.getProjectName(); } - public Resource(File file, IResource iRes, String projectName) { + public Resource(File file, IResource resource) { this.file = file; - this.iRes = iRes; - this.projectName = projectName; + this.resource = resource; } - public Resource(File file, String projectName) { - this(file, null, projectName); + public Resource(File file) { + this(file, null); } - public Resource(IResource iRes) { - this(iRes.getLocation().toFile(), iRes, iRes.getProject().getName()); + public Resource(IResource resource) { + this(resource.getLocation().toFile(), resource); } public File getFile() { return file; } - public IResource getIResource() { - return iRes; + public IResource getResource() { + return resource; } public String getWindowsDrive() { if (windowsDrive == null) { - getFullPath(); + getResourceLocation(); // Try to extract drive on Win32 - if (fullPath.indexOf(":") != -1) { - windowsDrive = fullPath.substring(0, fullPath.indexOf(":")); + if (resourceLocation.indexOf(":") != -1) { + windowsDrive = resourceLocation.substring(0, resourceLocation.indexOf(":")); } else { windowsDrive = ""; } @@ -79,47 +78,94 @@ public String getWindowsDrive() { return windowsDrive; } - public String getFullPath() { - if (fullPath == null) { - fullPath = file.toString(); + public String getContainerLocation() { + if (containerLocation == null) { + if (file.isDirectory()) { + containerLocation = file.getPath(); + } else { + containerLocation = file.getParent(); + } } - return fullPath; + return containerLocation; } - public String getParentPath() { - if (parentPath == null) { - if (file.isDirectory()) { - parentPath = getFile().getPath(); + public String getContainerName() { + if (resource != null) { + if (resource.getType() == IResource.FILE) { + return resource.getParent().getName(); + } else { + return resource.getName(); + } + } else { + if (file.isFile()) { + return file.getParentFile().getName(); } else { - parentPath = file.getParent(); - fileName = file.getName(); + return file.getName(); + } + } + } + + public String getContainerPath() { + if (resource != null) { + if (resource.getType() == IResource.FILE) { + return resource.getParent().getFullPath().toString(); + } else { + return resource.getFullPath().toString(); } } - return parentPath; + return ""; } - public String getParentName() { - if (iRes != null) { - return iRes.getParent().getName(); + public String getResourceLocation() { + if (resourceLocation == null) { + resourceLocation = file.getPath(); } - return file.getParentFile().getName(); + return resourceLocation; } - public String getFileName() { - if (fileName == null) { - if (file.isDirectory()) { - fileName = ""; + public String getResourceName() { + if (resourceName == null) { + if (resource != null) { + resourceName = resource.getName(); } else { - fileName = file.getName(); - } + /*if (file.isDirectory()) { + resourceName = ""; + } else {*/ + resourceName = file.getName(); + //} + } + } + return resourceName; + } + + public String getResourcePath() { + if (resource != null) { + return resource.getFullPath().toString(); + } + return ""; + } + + public String getProjectLocation() { + if (resource != null) { + return resource.getProject().getLocation().toFile().toString(); } - return fileName; + return ""; } public String getProjectName() { + if (resource != null) { + return resource.getProject().getName(); + } return projectName; } + public String getProjectPath() { + if (resource != null) { + return resource.getProject().getFullPath().toString(); + } + return ""; + } + public String getLineSeparator() { if (lineSeparator == null) { lineSeparator = System.getProperty("line.separator"); @@ -128,14 +174,17 @@ public String getLineSeparator() { } public String getFullQualifiedName() { - if (iRes != null) { + if (resource != null) { Bundle bundle = Platform.getBundle("org.eclipse.jdt.core"); if (bundle != null) { - IJavaElement element = JavaCore.create(iRes); + IJavaElement element = JavaCore.create(resource); if (element instanceof IPackageFragment) { return ((IPackageFragment)element).getElementName(); } else if (element instanceof ICompilationUnit) { - return ((ICompilationUnit)element).findPrimaryType().getFullyQualifiedName(); + IType type = ((ICompilationUnit)element).findPrimaryType(); + if (type != null) { + return type.getFullyQualifiedName(); + } } } } @@ -144,8 +193,8 @@ public String getFullQualifiedName() { public String getFullQualifiedPathName() { String fqcn = ""; - if (iRes != null) { - return iRes.getFullPath().toString(); + if (resource != null) { + return resource.getFullPath().toString(); /* String[] segments = iRes.getProjectRelativePath().segments(); for (int i=0;i= 1) { resource = new Resource[selectedObjects.length]; for (int i=0;i getCommands() { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java index 42f0e1da..63e6179a 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java @@ -127,12 +127,17 @@ public Control createDialogArea(Composite parent) { pageGroup2.setLayoutData(data2); pageGroup2.setFont(parent.getFont()); - createVariableLabel(pageGroup2, "${easyshell:drive}", "is the drive letter on Win32"); - createVariableLabel(pageGroup2, "${easyshell:container_loc}", "is the parent path*"); - createVariableLabel(pageGroup2, "${easyshell:resource_loc}", "is the full path*"); - createVariableLabel(pageGroup2, "${easyshell:resource_name}", "is the file name*"); - createVariableLabel(pageGroup2, "${easyshell:project_name}", "is the project name"); - createVariableLabel(pageGroup2, "${easyshell:line_separator}", "is the line separator"); + createVariableLabel(pageGroup2, "${easyshell:resource_loc}", "absolute path of file or directory"); + createVariableLabel(pageGroup2, "${easyshell:resource_name}", "name of file or directory"); + createVariableLabel(pageGroup2, "${easyshell:resource_path}", "relative path to workspace of file or directory"); + createVariableLabel(pageGroup2, "${easyshell:container_loc}", "absolute path of file directory or directory itself"); + createVariableLabel(pageGroup2, "${easyshell:container_name}", "name of file directory or directory itself"); + createVariableLabel(pageGroup2, "${easyshell:container_path}", "relative path to workspace of file directory or directory itself"); + createVariableLabel(pageGroup2, "${easyshell:project_loc}", "absolute path of project"); + createVariableLabel(pageGroup2, "${easyshell:project_name}", "name of project"); + createVariableLabel(pageGroup2, "${easyshell:project_path}", "relative path to workspace of project"); + createVariableLabel(pageGroup2, "${easyshell:line_separator}", "iline separator"); + createVariableLabel(pageGroup2, "${easyshell:windows_drive}", "drive letter of file or directory on Windows"); // TODO: to be enabled again, see https://github.com/anb0s/EasyShell/issues/61 setHelpAvailable(false); diff --git a/uuids.txt b/uuids.txt index 2debd189..c708d9f8 100644 --- a/uuids.txt +++ b/uuids.txt @@ -49,12 +49,12 @@ f6bcdd71-4687-46d8-bf34-2780bafd762a All 33043fe3-1a5f-46d7-b94e-9a02ef204e7d 88989d78-cf17-4750-91fc-6260055743ae +e6de32cc-342a-46a0-a766-ac74e7e4000d Do not use cd32fa5a-34d7-4551-8bd0-3aae0dc444d0 // was MAC OS X clipboard before Free -e6de32cc-342a-46a0-a766-ac74e7e4000d d2726c3f-6da3-46b5-8029-1c63d0ff6bd2 03e6678b-f67f-42ed-b65f-6b6f06ec0e8f c57a5d9f-491a-4b21-8a8b-9941b01cc049 From 8fcdb93e7cdc3a6eb0f118d1a97e7af638a7dd0a Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Mon, 1 Aug 2016 20:29:42 +0200 Subject: [PATCH 39/73] refactoring of variables Signed-off-by: Andre Bossert --- .../eclipse/easyshell/plugin/Resource.java | 60 ++++++------- .../CommandDataDefaultCollection.java | 16 ++-- .../plugin/preferences/CommandDataDialog.java | 16 ++-- .../easyshell/plugin/types/Variable.java | 86 +++++++++++++++++++ 4 files changed, 125 insertions(+), 53 deletions(-) create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/types/Variable.java diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/Resource.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/Resource.java index 6e4d1f88..dab5ee5e 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/Resource.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/Resource.java @@ -29,10 +29,6 @@ public class Resource { private IResource resource = null; // resolved - private String windowsDrive = null; - private String resourceLocation = null; - private String containerLocation = null; - private String resourceName = null; private String projectName = Activator.getResourceString("easyshell.plugin.name"); static private String lineSeparator = null; @@ -66,27 +62,21 @@ public IResource getResource() { } public String getWindowsDrive() { - if (windowsDrive == null) { - getResourceLocation(); - // Try to extract drive on Win32 - if (resourceLocation.indexOf(":") != -1) { - windowsDrive = resourceLocation.substring(0, resourceLocation.indexOf(":")); - } else { - windowsDrive = ""; + String loc = getResourceLocation(); + if (loc != null) { + int index = loc.indexOf(":"); + if (index != -1) { + return loc.substring(0, index); } } - return windowsDrive; + return ""; } public String getContainerLocation() { - if (containerLocation == null) { - if (file.isDirectory()) { - containerLocation = file.getPath(); - } else { - containerLocation = file.getParent(); - } + if (file.isDirectory()) { + return file.getPath(); } - return containerLocation; + return file.getParent(); } public String getContainerName() { @@ -117,25 +107,19 @@ public String getContainerPath() { } public String getResourceLocation() { - if (resourceLocation == null) { - resourceLocation = file.getPath(); - } - return resourceLocation; + return file.getPath(); } public String getResourceName() { - if (resourceName == null) { - if (resource != null) { - resourceName = resource.getName(); - } else { - /*if (file.isDirectory()) { - resourceName = ""; - } else {*/ - resourceName = file.getName(); - //} - } + if (resource != null) { + return resource.getName(); + } else { + /*if (file.isDirectory()) { + resourceName = ""; + } else {*/ + return file.getName(); + //} } - return resourceName; } public String getResourcePath() { @@ -173,6 +157,14 @@ public String getLineSeparator() { return lineSeparator; } + public String getFileSeparator() { + return System.getProperty("file.separator"); + } + + public String getPathSeparator() { + return System.getProperty("path.separator"); + } + public String getFullQualifiedName() { if (resource != null) { Bundle bundle = Platform.getBundle("org.eclipse.jdt.core"); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java index c33e171a..5da94207 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java @@ -65,9 +65,9 @@ public static List getCommandsNativeAsMenu(boolean sorted) { private void addWindowsCommands() { // Windows DOS-Shell - list.add(new CommandData("cd361a40-bb37-4fa2-9d2e-b62794294a59", PresetType.presetPlugin, OS.osWindows, "DOS-Shell", ResourceType.resourceTypeFileOrDirectory, Category.categoryOpen, CommandType.commandTypeExecute, + list.add(new CommandData("cd361a40-bb37-4fa2-9d2e-b62794294a59", PresetType.presetPlugin, OS.osWindows, "Command Prompt", ResourceType.resourceTypeFileOrDirectory, Category.categoryOpen, CommandType.commandTypeExecute, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} cmd.exe /K")); - list.add(new CommandData("f740984b-e9d5-4ebc-b9b5-c6b8527f886c", PresetType.presetPlugin, OS.osWindows, "DOS-Shell", ResourceType.resourceTypeFileOrDirectory, Category.categoryRun, CommandType.commandTypeExecute, + list.add(new CommandData("f740984b-e9d5-4ebc-b9b5-c6b8527f886c", PresetType.presetPlugin, OS.osWindows, "Command Prompt", ResourceType.resourceTypeFileOrDirectory, Category.categoryRun, CommandType.commandTypeExecute, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} ${easyshell:resource_name}")); // Windows Explorer list.add(new CommandData("ae0e5b6e-0b20-4c52-9708-ba7e317d1dee", PresetType.presetPlugin, OS.osWindows, "Explorer", ResourceType.resourceTypeFileOrDirectory, Category.categoryExplore, CommandType.commandTypeExecute, @@ -78,9 +78,9 @@ private void addWindowsCommands() { list.add(new CommandData("af2968d0-3a1a-40db-b3cb-e2e16293a285", PresetType.presetPlugin, OS.osWindows, "PowerShell", ResourceType.resourceTypeFileOrDirectory, Category.categoryRun, CommandType.commandTypeExecute, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} powershell.exe -command ./''${easyshell:resource_name}''")); // Windows Cygwin (Bash) - list.add(new CommandData("5b1e3806-a9ab-4866-b660-823ac388a575", PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceTypeFileOrDirectory, Category.categoryOpen, CommandType.commandTypeExecute, + list.add(new CommandData("5b1e3806-a9ab-4866-b660-823ac388a575", PresetType.presetPlugin, OS.osWindows, "Cygwin Bash", ResourceType.resourceTypeFileOrDirectory, Category.categoryOpen, CommandType.commandTypeExecute, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Cygwin\\bin\\bash.exe\"")); - list.add(new CommandData("2002e587-70a3-4204-b1a5-6faf6271ad08", PresetType.presetPlugin, OS.osWindows, "Cygwin (Bash)", ResourceType.resourceTypeFileOrDirectory, Category.categoryRun, CommandType.commandTypeExecute, + list.add(new CommandData("2002e587-70a3-4204-b1a5-6faf6271ad08", PresetType.presetPlugin, OS.osWindows, "Cygwin Bash", ResourceType.resourceTypeFileOrDirectory, Category.categoryRun, CommandType.commandTypeExecute, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Cygwin\\bin\\bash.exe\" -c ./''${easyshell:resource_name}''")); // Windows Console list.add(new CommandData("60fd43d2-d837-41d1-aaa3-3f5cab6bf0fb", PresetType.presetPlugin, OS.osWindows, "Console", ResourceType.resourceTypeFileOrDirectory, Category.categoryOpen, CommandType.commandTypeExecute, @@ -88,9 +88,9 @@ private void addWindowsCommands() { list.add(new CommandData("af6d97f2-f0a8-46e2-8234-74c0ee3e6007", PresetType.presetPlugin, OS.osWindows, "Console", ResourceType.resourceTypeFileOrDirectory, Category.categoryRun, CommandType.commandTypeExecute, "console.exe -w \"${easyshell:project_name}\" -d ${easyshell:container_loc} -r \"/k\\\"${easyshell:resource_name}\\\"\"")); // Windows Git-Bash - list.add(new CommandData("24419204-c8e5-4d79-a7b8-b14e93077cf0", PresetType.presetPlugin, OS.osWindows, "Git-Bash", ResourceType.resourceTypeFileOrDirectory, Category.categoryOpen, CommandType.commandTypeExecute, + list.add(new CommandData("24419204-c8e5-4d79-a7b8-b14e93077cf0", PresetType.presetPlugin, OS.osWindows, "Git Bash", ResourceType.resourceTypeFileOrDirectory, Category.categoryOpen, CommandType.commandTypeExecute, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Program Files (x86)\\Git\\bin\\bash.exe\" --login -i")); - list.add(new CommandData("ee790c7f-9c6d-40f9-84f6-51a948a59d45", PresetType.presetPlugin, OS.osWindows, "Git-Bash", ResourceType.resourceTypeFileOrDirectory, Category.categoryRun, CommandType.commandTypeExecute, + list.add(new CommandData("ee790c7f-9c6d-40f9-84f6-51a948a59d45", PresetType.presetPlugin, OS.osWindows, "Git Bash", ResourceType.resourceTypeFileOrDirectory, Category.categoryRun, CommandType.commandTypeExecute, "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Program Files (x86)\\Git\\bin\\bash.exe\" --login -i -c ./''${easyshell:resource_name}''")); // Windows ConEmu list.add(new CommandData("1bd62e22-cd93-4136-b643-1cbb9579c195", PresetType.presetPlugin, OS.osWindows, "ConEmu", ResourceType.resourceTypeFileOrDirectory, Category.categoryOpen, CommandType.commandTypeExecute, @@ -209,8 +209,8 @@ private static List getDefaultCommands() { case osUnknown: break; case osWindows: - addNotNull(listDefault, getCommandData(listOS, "DOS-Shell", Category.categoryOpen)); - addNotNull(listDefault, getCommandData(listOS, "DOS-Shell", Category.categoryRun)); + addNotNull(listDefault, getCommandData(listOS, ".*Prompt.*", Category.categoryOpen)); + addNotNull(listDefault, getCommandData(listOS, ".*Prompt.*", Category.categoryRun)); addNotNull(listDefault, getCommandData(listOS, "Explorer", Category.categoryExplore)); break; case osLinux: diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java index 63e6179a..59b0157b 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java @@ -38,6 +38,7 @@ import de.anbos.eclipse.easyshell.plugin.types.Category; import de.anbos.eclipse.easyshell.plugin.types.CommandType; import de.anbos.eclipse.easyshell.plugin.types.ResourceType; +import de.anbos.eclipse.easyshell.plugin.types.Variable; public class CommandDataDialog extends StatusDialog { @@ -127,17 +128,10 @@ public Control createDialogArea(Composite parent) { pageGroup2.setLayoutData(data2); pageGroup2.setFont(parent.getFont()); - createVariableLabel(pageGroup2, "${easyshell:resource_loc}", "absolute path of file or directory"); - createVariableLabel(pageGroup2, "${easyshell:resource_name}", "name of file or directory"); - createVariableLabel(pageGroup2, "${easyshell:resource_path}", "relative path to workspace of file or directory"); - createVariableLabel(pageGroup2, "${easyshell:container_loc}", "absolute path of file directory or directory itself"); - createVariableLabel(pageGroup2, "${easyshell:container_name}", "name of file directory or directory itself"); - createVariableLabel(pageGroup2, "${easyshell:container_path}", "relative path to workspace of file directory or directory itself"); - createVariableLabel(pageGroup2, "${easyshell:project_loc}", "absolute path of project"); - createVariableLabel(pageGroup2, "${easyshell:project_name}", "name of project"); - createVariableLabel(pageGroup2, "${easyshell:project_path}", "relative path to workspace of project"); - createVariableLabel(pageGroup2, "${easyshell:line_separator}", "iline separator"); - createVariableLabel(pageGroup2, "${easyshell:windows_drive}", "drive letter of file or directory on Windows"); + // create variable labels + for(int i=1;i getNamesAsList() { + List list = new ArrayList(); + for(int i = 0; i < Variable.values().length; i++) { + list.add(Variable.values()[i].getName()); + } + return list; + } +} From b86bf85ae658c016661f204fea9e0ca1bb4bc8c4 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Tue, 2 Aug 2016 23:33:20 +0200 Subject: [PATCH 40/73] more generic refactoring of variables - added path_separator and file_separator Signed-off-by: Andre Bossert --- .../plugin/DynamicVariableResolver.java | 33 +----- .../plugin/preferences/CommandDataDialog.java | 2 +- .../plugin/types/IVariableResolver.java | 18 +++ .../easyshell/plugin/types/Variable.java | 110 +++++++++++++++--- .../easyshell/plugin/types/Variables.java | 27 +++++ 5 files changed, 143 insertions(+), 47 deletions(-) create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/types/IVariableResolver.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/types/Variables.java diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/DynamicVariableResolver.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/DynamicVariableResolver.java index 18f4d6f7..83ba9d13 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/DynamicVariableResolver.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/DynamicVariableResolver.java @@ -16,6 +16,7 @@ import org.eclipse.core.variables.IDynamicVariableResolver; import de.anbos.eclipse.easyshell.plugin.types.Quotes; +import de.anbos.eclipse.easyshell.plugin.types.Variables; public class DynamicVariableResolver implements IDynamicVariableResolver { @@ -25,7 +26,6 @@ public class DynamicVariableResolver implements IDynamicVariableResolver { @Override public String resolveValue(IDynamicVariable variable, String argument) throws CoreException { - // easyshell own variables String variableName = variable.getName(); if (variableName.equals("easyshell")) { return handleOwnVariable(argument); @@ -35,38 +35,11 @@ public String resolveValue(IDynamicVariable variable, String argument) } private String handleOwnVariable(String argument) { - if (argument.equals("windows_drive")) { - return resource.getWindowsDrive(); // ${easyshell:windows_drive} == {0} - } else if (argument.equals("line_separator")) { - return resource.getLineSeparator(); // ${easyshell:line_separator} == {5} - } else if (argument.equals("qualified_name")) { - return resource.getFullQualifiedName(); // ${easyshell:qualified_name} - } - // here we have a eclipse variable embedded in easyshell variable as parameter - return handleEclipseVariable(argument, null); + return autoQuotes(Variables.getMap().get(argument).resolve(resource)); } private String handleEclipseVariable(String variable, String argument) { - if (variable.equals("container_loc")) { - return autoQuotes(resource.getContainerLocation()); // ${easyshell:container_loc} == {1} - } else if (variable.equals("container_name")) { - return autoQuotes(resource.getContainerName()); // ${easyshell:container_name} - } else if (variable.equals("container_path")) { - return autoQuotes(resource.getContainerPath()); // ${easyshell:container_path} - } else if (variable.equals("resource_loc")) { - return autoQuotes(resource.getResourceLocation()); // ${easyshell:resource_loc} == {2} - } else if (variable.equals("resource_name")) { - return autoQuotes(resource.getResourceName()); // ${easyshell:resource_name} == {3} - } else if (variable.equals("resource_path")) { - return autoQuotes(resource.getResourcePath()); // ${easyshell:resource_path} - } else if (variable.equals("project_loc")) { - return autoQuotes(resource.getProjectLocation()); // ${easyshell:project_loc_loc} - } else if (variable.equals("project_name")) { - return resource.getProjectName(); // ${easyshell:project_name} == {4} - } else if (variable.equals("project_path")) { - return autoQuotes(resource.getProjectPath()); // ${easyshell:project_path} - } - return null; + return autoQuotes(Variables.getMap().get(argument).resolve(resource)); } public static Resource getResource() { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java index 59b0157b..9dc7513d 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java @@ -130,7 +130,7 @@ public Control createDialogArea(Composite parent) { // create variable labels for(int i=1;i getNamesAsList() { } return list; } + public IVariableResolver getResolver() { + return resolver; + } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Variables.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Variables.java new file mode 100644 index 00000000..733e8711 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Variables.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.types; + +import java.util.HashMap; +import java.util.Map; + +public class Variables { + static Map map = new HashMap(); + public static Map getMap() { + return map; + } + static { + for(int i=0;i Date: Thu, 4 Aug 2016 16:54:10 +0200 Subject: [PATCH 41/73] added new name patterns to have similar names like in other Eclipse and OS tools Signed-off-by: Andre Bossert --- .../CommandDataDefaultCollection.java | 8 ++- .../plugin/preferences/MenuData.java | 42 +++++++++---- .../plugin/preferences/MenuDataDialog.java | 59 +++++++++++-------- .../easyshell/plugin/types/MenuNameType.java | 14 +++-- .../easyshell/plugin/types/Version.java | 3 +- 5 files changed, 84 insertions(+), 42 deletions(-) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java index 5da94207..ba02a7d3 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java @@ -24,6 +24,7 @@ import de.anbos.eclipse.easyshell.plugin.types.OS; import de.anbos.eclipse.easyshell.plugin.types.PresetType; import de.anbos.eclipse.easyshell.plugin.types.ResourceType; +import de.anbos.eclipse.easyshell.plugin.types.Variable; public class CommandDataDefaultCollection { @@ -47,6 +48,7 @@ public static List getCommandsNativeAsMenu(boolean sorted) { CommandData cmdData = list.get(i); // use the same id like the default command to have same defaults MenuData newData = new MenuData(cmdData.getId(), cmdData.getId()); + newData.setNameTypeFromCategory(cmdData.getCategory()); if (sorted) { newData.setPosition(i); } @@ -181,8 +183,12 @@ private void addAllOSCommands() { list.add(new CommandData("88989d78-cf17-4750-91fc-6260055743ae", PresetType.presetPlugin, Utils.getOS(), "Qualified Name", ResourceType.resourceTypeFileOrDirectory, Category.categoryClipboard, CommandType.commandTypeClipboard, "${easyshell:qualified_name}${easyshell:line_separator}")); // Clipboard - Variables Test + String varTestString = ""; + for(int i=1;i getCommands() { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java index 813c3843..0219a9e5 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java @@ -14,6 +14,7 @@ import java.util.StringTokenizer; import java.util.UUID; +import de.anbos.eclipse.easyshell.plugin.types.Category; import de.anbos.eclipse.easyshell.plugin.types.MenuNameType; import de.anbos.eclipse.easyshell.plugin.types.Version; @@ -123,7 +124,6 @@ public boolean deserialize(Version version, String value, StringTokenizer tokeni // read the new one setCommandId(tokenizer.nextToken()); setNameType(nameType); - setNamePattern(namePatternReaded); } else { // read previous command data members CommandData oldData = new CommandData(); @@ -133,11 +133,6 @@ public boolean deserialize(Version version, String value, StringTokenizer tokeni // set name type and read the old name as pattern and convert to new if (version.getId() >= Version.v2_0_002.getId()) { setNameType(nameType); - if (nameType == MenuNameType.menuNameTypeUser) { - setNamePattern(namePatternReaded); - } else { - setNamePattern(nameType.getPattern()); - } } else { // check if readed name is the same, like expanded from patterns for (MenuNameType type : MenuNameType.getAsList()) { @@ -148,10 +143,14 @@ public boolean deserialize(Version version, String value, StringTokenizer tokeni } } setNameType(nameType); - // if not found set the readed value - if (nameType == MenuNameType.menuNameTypeUser) { - setNamePattern(namePatternReaded); - } + } + } + if (nameType == MenuNameType.menuNameTypeUser) { + setNamePattern(namePatternReaded); + } else if (version.getId() < Version.v2_0_004.getId()) { + // convert to new names types + if (nameType == MenuNameType.menuNameTypeGeneric1) { + setNameTypeFromCategory(); } } return true; @@ -204,4 +203,27 @@ public CommandData getCommandData() { return CommandDataStore.instance().getById(getCommandId()); } + public void setNameTypeFromCategory() { + CommandData newData = getCommandData(); + if (newData != null) { + setNameTypeFromCategory(newData.getCategory()); + } + } + + public void setNameTypeFromCategory(Category category) { + switch(category) { + case categoryDefault: setNameType(MenuNameType.menuNameTypeDefaultApplication); + break; + case categoryOpen: setNameType(MenuNameType.menuNameTypeOpenHere); + break; + case categoryRun: setNameType(MenuNameType.menuNameTypeGeneric2); + break; + case categoryExplore: setNameType(MenuNameType.menuNameTypeShowIn); + break; + case categoryClipboard: setNameType(MenuNameType.menuNameTypeCopyToClipboard); + break; + } + + } + } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java index 9eec6f03..91cf80df 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java @@ -47,7 +47,7 @@ public class MenuDataDialog extends StatusDialog { - private MenuData data; + private MenuData menuData; private List cmdList; private Button enabledCheckBox; @@ -62,9 +62,9 @@ public class MenuDataDialog extends StatusDialog { private Button editButton; private Button removeButton; - public MenuDataDialog(Shell parent, MenuData data, List cmdList, boolean edit) { + public MenuDataDialog(Shell parent, MenuData menuData, List cmdList, boolean edit) { super(parent); - this.data = data; + this.menuData = menuData; this.cmdList = cmdList; // do layout and title setShellStyle(getShellStyle() | SWT.MAX); @@ -113,20 +113,20 @@ public Control createDialogArea(Composite parent) { // type combo createNameTypeCombo(pageGroup1); // create input nameText field - namePatternText = createTextField(pageGroup1, Activator.getResourceString("easyshell.menu.editor.dialog.label.pattern"), data.getNamePattern(), true); + namePatternText = createTextField(pageGroup1, Activator.getResourceString("easyshell.menu.editor.dialog.label.pattern"), menuData.getNamePattern(), true); namePatternText.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { - boolean isUserDefined = data.getNameType() == MenuNameType.menuNameTypeUser; + boolean isUserDefined = menuData.getNameType() == MenuNameType.menuNameTypeUser; if (isUserDefined) { Text text = (Text)e.widget; - data.setNamePattern(text.getText()); - menuNameText.setText(data.getNameExpanded()); + menuData.setNamePattern(text.getText()); + menuNameText.setText(menuData.getNameExpanded()); } } }); - menuNameText = createTextField(pageGroup1, Activator.getResourceString("easyshell.menu.editor.dialog.label.name"), data.getNameExpanded(), false); + menuNameText = createTextField(pageGroup1, Activator.getResourceString("easyshell.menu.editor.dialog.label.name"), menuData.getNameExpanded(), false); // define group2 Group pageGroup2 = new Group(pageComponent, SWT.SHADOW_ETCHED_IN); @@ -144,7 +144,7 @@ public void modifyText(ModifyEvent e) { // create selected command combo createCommandCombo(pageGroup2); createNewButton(font, pageGroup2, gridData2); // create input commandText field - commandText = createTextField(pageGroup2, Activator.getResourceString("easyshell.menu.editor.dialog.label.command"), data.getCommandData().getCommand(), false); + commandText = createTextField(pageGroup2, Activator.getResourceString("easyshell.menu.editor.dialog.label.command"), menuData.getCommandData().getCommand(), false); createCopyButton(font, pageGroup2, gridData2); createLabel(pageGroup2, "");createLabel(pageGroup2, ""); createEditButton(font, pageGroup2, gridData2); @@ -229,10 +229,10 @@ protected void okPressed() { if (!validateValues()) { return; } - data.setEnabled(enabledCheckBox.getSelection()); - data.setNameType(getAllNameTypes()[nameTypeCombo.getSelectionIndex()]); - data.setNamePattern(namePatternText.getText()); - data.setCommandId(cmdList.get(commandCombo.getSelectionIndex()).getId()); + menuData.setEnabled(enabledCheckBox.getSelection()); + menuData.setNameType(getAllNameTypes()[nameTypeCombo.getSelectionIndex()]); + menuData.setNamePattern(namePatternText.getText()); + menuData.setCommandId(cmdList.get(commandCombo.getSelectionIndex()).getId()); super.okPressed(); } @@ -315,7 +315,7 @@ private void removeDialog() { commands.add(data); // get referenced menus and remove the the actual menus menus.addAll(MenuDataStore.instance().getRefencedBy(data.getId())); - menus.remove(this.data); + menus.remove(this.menuData); // ask user String commandNames = commandCombo.getItem(index); String title = Activator.getResourceString("easyshell.menu.editor.dialog.title.remove"); @@ -387,7 +387,7 @@ private boolean validateValues() { int index = commandCombo.getSelectionIndex(); CommandData data = cmdList.get(index); List menus = MenuDataStore.instance().getRefencedBy(data.getId()); - menus.remove(this.data); + menus.remove(this.menuData); if (menus.size() >0) { title = Activator.getResourceString("easyshell.menu.editor.dialog.title.duplicate"); String commandNames = commandCombo.getItem(index); @@ -417,7 +417,7 @@ private void createEnabledCheckBox(Composite parent) { createLabel(parent, Activator.getResourceString("easyshell.menu.editor.dialog.label.active")); // draw checkbox enabledCheckBox = new Button(parent,SWT.CHECK); - enabledCheckBox.setSelection(this.data.isEnabled()); + enabledCheckBox.setSelection(this.menuData.isEnabled()); } private String[] getAllCommandsAsComboNames(List list) { @@ -450,11 +450,17 @@ private void createCommandCombo(Composite parent) { public void widgetSelected(SelectionEvent e) { int index = commandCombo.getSelectionIndex(); //String text = commandCombo.getItem(index); - data.setCommandId(cmdList.get(index).getId()); - commandText.setText(data.getCommandData().getCommand()); - boolean isUserDefined = data.getCommandData().getPresetType() == PresetType.presetUser; + CommandData cmdData = cmdList.get(index); + menuData.setCommandId(cmdData.getId()); + if (menuData.getNameType() != MenuNameType.menuNameTypeUser) { + menuData.setNameTypeFromCategory(cmdData.getCategory()); + } + commandText.setText(menuData.getCommandData().getCommand()); + boolean isUserDefined = menuData.getCommandData().getPresetType() == PresetType.presetUser; //editButton.setEnabled(isUserDefined); removeButton.setEnabled(isUserDefined); + // updates & refreshes + updateTypeComboSelection(); refreshNameTypeCombo(); } @Override @@ -463,7 +469,7 @@ public void widgetDefaultSelected(SelectionEvent e) { } }); for(int i = 0 ; i < cmdList.size() ; i++) { - if (cmdList.get(i).equals(this.data.getCommandData())) { + if (cmdList.get(i).equals(this.menuData.getCommandData())) { commandCombo.select(i); return; } @@ -485,10 +491,10 @@ private void createNameTypeCombo(Composite parent) { @Override public void widgetSelected(SelectionEvent e) { int index = nameTypeCombo.getSelectionIndex(); - data.setNameType(MenuNameType.getAsArray()[index]); - namePatternText.setText(data.getNamePattern()); - menuNameText.setText(data.getNameExpanded()); - boolean isUserDefined = data.getNameType() == MenuNameType.menuNameTypeUser; + menuData.setNameType(MenuNameType.getAsArray()[index]); + namePatternText.setText(menuData.getNamePattern()); + menuNameText.setText(menuData.getNameExpanded()); + boolean isUserDefined = menuData.getNameType() == MenuNameType.menuNameTypeUser; namePatternText.setEditable(isUserDefined); } @Override @@ -496,9 +502,12 @@ public void widgetDefaultSelected(SelectionEvent e) { // TODO Auto-generated method stub } }); + updateTypeComboSelection(); + } + private void updateTypeComboSelection() { for(int i = 0 ; i < MenuNameType.values().length ; i++) { - if (MenuNameType.values()[i].equals(this.data.getNameType())) { + if (MenuNameType.values()[i].equals(this.menuData.getNameType())) { nameTypeCombo.select(MenuNameType.values()[i].getId()); return; } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/MenuNameType.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/MenuNameType.java index 52e9601c..e749e769 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/MenuNameType.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/MenuNameType.java @@ -15,11 +15,15 @@ import java.util.List; public enum MenuNameType { - menuNameTypeUnknown(-1, "Unknown", ""), - menuNameTypeUser(0, "User defined", "${easyshell:command_name}"), - menuNameTypeGeneric1(1, ": ", "${easyshell:command_category}: ${easyshell:command_name}"), - menuNameTypeGeneric2(2, " with ", "${easyshell:command_category} with ${easyshell:command_name}"), - menuNameTypeGeneric3(3, " with ", "${easyshell:command_category} with ${easyshell:command_os} ${easyshell:command_name}"); + menuNameTypeUnknown( -1, "Unknown", ""), + menuNameTypeUser( 0, "User defined", "${easyshell:command_name}"), + menuNameTypeDefaultApplication( 1, "Open with default application", "Open with default Application"), + menuNameTypeOpenHere( 2, "Open Here", "Open ${easyshell:command_name} Here"), + menuNameTypeShowIn( 3, "Show in ", "Show in ${easyshell:command_name}"), + menuNameTypeCopyToClipboard( 4, "Copy to Clipboard", "Copy ${easyshell:command_name} to Clipboard"), + menuNameTypeGeneric1( 5, ": ", "${easyshell:command_category}: ${easyshell:command_name}"), + menuNameTypeGeneric2( 6, " with ", "${easyshell:command_category} with ${easyshell:command_name}"), + menuNameTypeGeneric3( 7, " with ", "${easyshell:command_category} with ${easyshell:command_os} ${easyshell:command_name}"); // attributes private final int id; private final String name; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Version.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Version.java index 3c9f87db..b8afdac6 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Version.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Version.java @@ -20,7 +20,8 @@ public enum Version { v1_4(0, "v1.4.x"), v2_0_001(1, "v2.0 beta 1"), v2_0_002(2, "v2.0 beta 2"), - v2_0_003(3, "v2.0 beta 3"); + v2_0_003(3, "v2.0 beta 3"), + v2_0_004(4, "v2.0 bata 4"); // actual version is always the last one! public static Version actual = Version.values()[Version.values().length-1]; // attributes From 73fb23613a2f5802454f624fa7d1b080f66133ab Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Mon, 22 Aug 2016 18:43:08 +0200 Subject: [PATCH 42/73] #77 add git-bash.exe (Git for Windows 2.x) preset Signed-off-by: Andre Bossert --- .../preferences/CommandDataDefaultCollection.java | 12 ++++++++---- uuids.txt | 4 ++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java index ba02a7d3..3377e6dc 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java @@ -90,10 +90,14 @@ private void addWindowsCommands() { list.add(new CommandData("af6d97f2-f0a8-46e2-8234-74c0ee3e6007", PresetType.presetPlugin, OS.osWindows, "Console", ResourceType.resourceTypeFileOrDirectory, Category.categoryRun, CommandType.commandTypeExecute, "console.exe -w \"${easyshell:project_name}\" -d ${easyshell:container_loc} -r \"/k\\\"${easyshell:resource_name}\\\"\"")); // Windows Git-Bash - list.add(new CommandData("24419204-c8e5-4d79-a7b8-b14e93077cf0", PresetType.presetPlugin, OS.osWindows, "Git Bash", ResourceType.resourceTypeFileOrDirectory, Category.categoryOpen, CommandType.commandTypeExecute, - "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Program Files (x86)\\Git\\bin\\bash.exe\" --login -i")); - list.add(new CommandData("ee790c7f-9c6d-40f9-84f6-51a948a59d45", PresetType.presetPlugin, OS.osWindows, "Git Bash", ResourceType.resourceTypeFileOrDirectory, Category.categoryRun, CommandType.commandTypeExecute, - "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Program Files (x86)\\Git\\bin\\bash.exe\" --login -i -c ./''${easyshell:resource_name}''")); + list.add(new CommandData("24419204-c8e5-4d79-a7b8-b14e93077cf0", PresetType.presetPlugin, OS.osWindows, "Git Bash v1.x", ResourceType.resourceTypeFileOrDirectory, Category.categoryOpen, CommandType.commandTypeExecute, + "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Program Files\\Git\\bin\\bash.exe\" --login -i")); + list.add(new CommandData("ee790c7f-9c6d-40f9-84f6-51a948a59d45", PresetType.presetPlugin, OS.osWindows, "Git Bash v1.x", ResourceType.resourceTypeFileOrDirectory, Category.categoryRun, CommandType.commandTypeExecute, + "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Program Files\\Git\\bin\\bash.exe\" --login -i -c ./''${easyshell:resource_name}''")); + list.add(new CommandData("d2726c3f-6da3-46b5-8029-1c63d0ff6bd2", PresetType.presetPlugin, OS.osWindows, "Git Bash v2.x", ResourceType.resourceTypeFileOrDirectory, true, "${easyshell:container_loc}", Category.categoryOpen, CommandType.commandTypeExecute, + "C:\\Program Files\\Git\\git-bash.exe")); + list.add(new CommandData("03e6678b-f67f-42ed-b65f-6b6f06ec0e8f", PresetType.presetPlugin, OS.osWindows, "Git Bash v2.x", ResourceType.resourceTypeFileOrDirectory, true, "${easyshell:container_loc}", Category.categoryRun, CommandType.commandTypeExecute, + "C:\\Program Files\\Git\\git-bash.exe -c ./''${easyshell:resource_name}''")); // Windows ConEmu list.add(new CommandData("1bd62e22-cd93-4136-b643-1cbb9579c195", PresetType.presetPlugin, OS.osWindows, "ConEmu", ResourceType.resourceTypeFileOrDirectory, Category.categoryOpen, CommandType.commandTypeExecute, "ConEmu.exe /Title \"${easyshell:project_name}\" /Dir \"${easyshell:container_loc}\" /Single /cmd cmd")); diff --git a/uuids.txt b/uuids.txt index c708d9f8..afd1905c 100644 --- a/uuids.txt +++ b/uuids.txt @@ -14,6 +14,8 @@ af2968d0-3a1a-40db-b3cb-e2e16293a285 af6d97f2-f0a8-46e2-8234-74c0ee3e6007 24419204-c8e5-4d79-a7b8-b14e93077cf0 ee790c7f-9c6d-40f9-84f6-51a948a59d45 +d2726c3f-6da3-46b5-8029-1c63d0ff6bd2 +03e6678b-f67f-42ed-b65f-6b6f06ec0e8f 1bd62e22-cd93-4136-b643-1cbb9579c195 c2b73077-ffd9-4fb7-9793-189be9f13ebb e487327c-dfdb-42e7-bf16-3b81a34e5703 @@ -55,8 +57,6 @@ Do not use cd32fa5a-34d7-4551-8bd0-3aae0dc444d0 // was MAC OS X clipboard before Free -d2726c3f-6da3-46b5-8029-1c63d0ff6bd2 -03e6678b-f67f-42ed-b65f-6b6f06ec0e8f c57a5d9f-491a-4b21-8a8b-9941b01cc049 95cacf98-9dfc-473f-b5d3-fe4961e66ae1 771c0bac-cdb2-47fe-a030-6b830d366da1 From 729b0fbe9fa05f0545ef66f67b47ad91f79bbff8 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Tue, 23 Aug 2016 19:52:48 +0200 Subject: [PATCH 43/73] #51 please support https://github.com/cmderdev/cmder Signed-off-by: Andre Bossert --- .../plugin/preferences/CommandDataDefaultCollection.java | 2 ++ uuids.txt | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java index 3377e6dc..f0f1c83c 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java @@ -103,6 +103,8 @@ private void addWindowsCommands() { "ConEmu.exe /Title \"${easyshell:project_name}\" /Dir \"${easyshell:container_loc}\" /Single /cmd cmd")); list.add(new CommandData("c2b73077-ffd9-4fb7-9793-189be9f13ebb", PresetType.presetPlugin, OS.osWindows, "ConEmu", ResourceType.resourceTypeFileOrDirectory, Category.categoryRun, CommandType.commandTypeExecute, "ConEmu.exe /Title \"${easyshell:project_name}\" /Dir \"${easyshell:container_loc}\" /Single /cmd \"${easyshell:resource_name}\"")); + list.add(new CommandData("c57a5d9f-491a-4b21-8a8b-9941b01cc049", PresetType.presetPlugin, OS.osWindows, "Cmder", ResourceType.resourceTypeFileOrDirectory, Category.categoryOpen, CommandType.commandTypeExecute, + "cmder.exe /START \"${easyshell:container_loc}\"")); // Windows TotalCommander list.add(new CommandData("e487327c-dfdb-42e7-bf16-3b81a34e5703", PresetType.presetPlugin, OS.osWindows, "TotalCommander", ResourceType.resourceTypeFileOrDirectory, Category.categoryExplore, CommandType.commandTypeExecute, "cmd.exe /C totalcmd64.exe /O /T ${easyshell:container_loc}")); diff --git a/uuids.txt b/uuids.txt index afd1905c..b71f8c71 100644 --- a/uuids.txt +++ b/uuids.txt @@ -18,6 +18,7 @@ d2726c3f-6da3-46b5-8029-1c63d0ff6bd2 03e6678b-f67f-42ed-b65f-6b6f06ec0e8f 1bd62e22-cd93-4136-b643-1cbb9579c195 c2b73077-ffd9-4fb7-9793-189be9f13ebb +c57a5d9f-491a-4b21-8a8b-9941b01cc049 e487327c-dfdb-42e7-bf16-3b81a34e5703 67aa9dff-6bbb-4b47-8b43-8a82a7a279fa @@ -57,7 +58,7 @@ Do not use cd32fa5a-34d7-4551-8bd0-3aae0dc444d0 // was MAC OS X clipboard before Free -c57a5d9f-491a-4b21-8a8b-9941b01cc049 + 95cacf98-9dfc-473f-b5d3-fe4961e66ae1 771c0bac-cdb2-47fe-a030-6b830d366da1 61c4fef4-470a-45b1-98df-ccf9d7d91143 From be7ff84da963fc02ef5010ff13d843d7e74630ed Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Tue, 23 Aug 2016 19:57:17 +0200 Subject: [PATCH 44/73] #68 [v2.0] issues found in beta 3 #16 Copy Fully Qualified Class Name #51 please support https://github.com/cmderdev/cmder #72 [v2.0] add *_path eclipse variables #77 add git-bash.exe (Git for Windows 2.x) preset Signed-off-by: Andre Bossert --- .../2.0/2.0.0.v20160823-1756/artifacts.jar | Bin 0 -> 732 bytes .../2.0/2.0.0.v20160823-1756/content.jar | Bin 0 -> 5763 bytes ....easyshell.feature_2.0.0.v20160823-1756.jar | Bin 0 -> 5134 bytes ...e.easyshell.plugin_2.0.0.v20160823-1756.jar | Bin 0 -> 147920 bytes .../updates/testing/2.0/compositeArtifacts.xml | 5 +++-- site/updates/testing/2.0/compositeContent.xml | 5 +++-- 6 files changed, 6 insertions(+), 4 deletions(-) create mode 100644 site/updates/testing/2.0/2.0.0.v20160823-1756/artifacts.jar create mode 100644 site/updates/testing/2.0/2.0.0.v20160823-1756/content.jar create mode 100644 site/updates/testing/2.0/2.0.0.v20160823-1756/features/de.anbos.eclipse.easyshell.feature_2.0.0.v20160823-1756.jar create mode 100644 site/updates/testing/2.0/2.0.0.v20160823-1756/plugins/de.anbos.eclipse.easyshell.plugin_2.0.0.v20160823-1756.jar diff --git a/site/updates/testing/2.0/2.0.0.v20160823-1756/artifacts.jar b/site/updates/testing/2.0/2.0.0.v20160823-1756/artifacts.jar new file mode 100644 index 0000000000000000000000000000000000000000..ee2c8207835d4313edc41fc2f43ef2b468bbbc9e GIT binary patch literal 732 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 literal 0 HcmV?d00001 diff --git a/site/updates/testing/2.0/2.0.0.v20160823-1756/features/de.anbos.eclipse.easyshell.feature_2.0.0.v20160823-1756.jar b/site/updates/testing/2.0/2.0.0.v20160823-1756/features/de.anbos.eclipse.easyshell.feature_2.0.0.v20160823-1756.jar new file mode 100644 index 0000000000000000000000000000000000000000..35424e90560f71e64f28c47188a398e1cbca85c6 GIT binary patch literal 5134 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 literal 0 HcmV?d00001 diff --git a/site/updates/testing/2.0/2.0.0.v20160823-1756/plugins/de.anbos.eclipse.easyshell.plugin_2.0.0.v20160823-1756.jar b/site/updates/testing/2.0/2.0.0.v20160823-1756/plugins/de.anbos.eclipse.easyshell.plugin_2.0.0.v20160823-1756.jar new file mode 100644 index 0000000000000000000000000000000000000000..db01ef8ff4ea1de854f405a63f00962dda0a3857 GIT binary patch literal 147920 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
x0ZpIA=2KYAL)8L~9p9 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

~%v&Ai9o5j+4 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

VDwP%|M#B`!_Kt+3N^%XK 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 - + - + + diff --git a/site/updates/testing/2.0/compositeContent.xml b/site/updates/testing/2.0/compositeContent.xml index 33debdd6..3abf89fe 100644 --- a/site/updates/testing/2.0/compositeContent.xml +++ b/site/updates/testing/2.0/compositeContent.xml @@ -2,12 +2,13 @@ - + - + + From da546372fdd6e5307cb5e232e31ea7fff6b9ec2f Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Thu, 1 Sep 2016 18:50:52 +0200 Subject: [PATCH 45/73] #55 [v2.0] migration support from legacy EasyShell v1.x Signed-off-by: Andre Bossert --- .../eclipse/easyshell/plugin/Activator.java | 9 +- .../easyshell/plugin/legacy/Debug.java | 43 ++ .../easyshell/plugin/legacy/LinuxDesktop.java | 47 ++ .../plugin/legacy/PreferenceEntry.java | 59 +++ .../easyshell/plugin/legacy/PrefsV1_4.java | 366 ++++++++++++++ .../easyshell/plugin/legacy/PrefsV1_5.java | 475 ++++++++++++++++++ .../easyshell/plugin/legacy/Quotes.java | 47 ++ .../easyshell/plugin/legacy/Tokenizer.java | 43 ++ .../plugin/preferences/Initializer.java | 63 ++- .../easyshell/plugin/types/Version.java | 10 +- 10 files changed, 1134 insertions(+), 28 deletions(-) create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/Debug.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/LinuxDesktop.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/PreferenceEntry.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/PrefsV1_4.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/PrefsV1_5.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/Quotes.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/Tokenizer.java diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java index ebc9855a..a70b4644 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/Activator.java @@ -226,14 +226,19 @@ public static void logDebug(String string) { public IPreferenceStore getPreferenceStore() { // Create the preference store lazily. if (myPreferenceStore == null) { - myPreferenceStore = getNewPreferenceStoreByVersion(Version.actual.name()); + myPreferenceStore = getPreferenceStoreByVersion(Version.actual.name()); } return myPreferenceStore; } - public IPreferenceStore getNewPreferenceStoreByVersion(String version) { + public IPreferenceStore getPreferenceStoreByVersion(String version) { String pluginNodeName = getBundle().getSymbolicName(); return new ScopedPreferenceStore(InstanceScope.INSTANCE, pluginNodeName + "/" + version, pluginNodeName); } + public IPreferenceStore getLegacyPreferenceStore() { + String pluginNodeName = "com.tetrade.eclipse.plugins.easyshell"; + return new ScopedPreferenceStore(InstanceScope.INSTANCE, pluginNodeName, pluginNodeName); + } + } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/Debug.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/Debug.java new file mode 100644 index 00000000..cfebc17e --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/Debug.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.legacy; + +/** + * Debug. + */ +public enum Debug { + debugNo(0, "No"), + debugYes(1, "Yes"); + // attributes + private final int id; + private final String mode; + // construct + Debug(int id, String mode) { + this.id = id; + this.mode = mode; + } + public int getId() { + return id; + } + public String getMode() { + return mode; + } + public static Debug getFromId(int id) { + Debug ret = debugNo; + for(int i = 0; i < Debug.values().length; i++) { + if (Debug.values()[i].getId() == id) { + ret = Debug.values()[i]; + } + } + return ret; + } +} \ No newline at end of file diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/LinuxDesktop.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/LinuxDesktop.java new file mode 100644 index 00000000..6ab40a8c --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/LinuxDesktop.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.legacy; + +/** + * Linux desktops. + */ +public enum LinuxDesktop { + desktopUnknown(0, "Unknown"), + desktopKde(1, "KDE"), + desktopGnome(2, "Gnome"), + desktopCinnamon(3, "Cinnamon"), + desktopCde(4, "CDE"), + desktopXfce(5, "Xfce"); + // attributes + private final int id; + private final String name; + // construct + LinuxDesktop(int id, String name) { + this.id = id; + this.name = name; + } + public int getId() { + return id; + } + public String getName() { + return name; + } + public static LinuxDesktop getFromId(int id) { + LinuxDesktop ret = desktopUnknown; + for(int i = 0; i < LinuxDesktop.values().length; i++) { + if (LinuxDesktop.values()[i].getId() == id) { + ret = LinuxDesktop.values()[i]; + } + } + return ret; + } +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/PreferenceEntry.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/PreferenceEntry.java new file mode 100644 index 00000000..96325adf --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/PreferenceEntry.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.legacy; + +/** + * Strings for preference store. + */ +public enum PreferenceEntry { + preferenceTargetOpen(0, "targetPreference"), + preferenceTargetRun(1, "targetRunPreference"), + preferenceTargetExplore(2, "targetExplorePreference"), + preferenceTargetCopyPath(3, "targetCopyPathPreference"), + preferenceListId(4, "listPreference"), + preferenceListString(5, "IdStr"), + preferenceQuotes(6, "QuotesStr"), + preferenceDebug(7, "DebugStr"), + preferenceTokenizer(8, "TokenizerStr"), + preferenceTargetEnabled(9, "targetEnabled"); + // attributes + private final int id; + private final String preferenceString; + // construct + PreferenceEntry(int id, String pref) { + this.id = id; + this.preferenceString = pref; + } + public int getId() { + return id; + } + public String getString() { + return preferenceString; + } + public String getString(int instId) { + if (instId == 0) { + return getString(); + } else { + return getString() + (new Integer(instId)).toString(); + } + } + public static PreferenceEntry getFromId(int id) { + PreferenceEntry ret = preferenceTargetOpen; + for(int i = 0; i < PreferenceEntry.values().length; i++) { + if (PreferenceEntry.values()[i].getId() == id) { + ret = PreferenceEntry.values()[i]; + break; + } + } + return ret; + } +}; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/PrefsV1_4.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/PrefsV1_4.java new file mode 100644 index 00000000..eb17f5fc --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/PrefsV1_4.java @@ -0,0 +1,366 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.legacy; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.preference.IPreferenceStore; + +import de.anbos.eclipse.easyshell.plugin.legacy.PrefsV1_5.Command; +import de.anbos.eclipse.easyshell.plugin.preferences.CommandData; +import de.anbos.eclipse.easyshell.plugin.preferences.MenuData; + +public class PrefsV1_4 { + + /** + * Commands. + */ + private enum Command { + cmdUnknown(0, "Unknown shell / file browser", + "open {1}", + "cd {1} && run ./''{3}''", + "explore {2}", + "{2}{5}" + ), + cmdWinDOS(1, "Windows DOS-Shell / Explorer", + "cmd.exe /C start \"{4}\" /D {1} cmd.exe /K", + "cmd.exe /C start \"{4}\" /D {1} {3}", + "explorer.exe /select, {2}", + "{2}{5}" + ), + cmdWinPower(2, "Windows PowerShell / Explorer", + "cmd.exe /C start \"{4}\" /D {1} powershell.exe", + "cmd.exe /C start \"{4}\" /D {1} powershell.exe -command ./''{3}''", + "explorer.exe /select, {2}", + "{2}{5}" + ), + cmdWinCyg(3, "Windows Cygwin (Bash) / Explorer", + "cmd.exe /C start \"{4}\" /D {1} \"C:\\Cygwin\\bin\\bash.exe\"", + "cmd.exe /C start \"{4}\" /D {1} \"C:\\Cygwin\\bin\\bash.exe\" -c ./''{3}''", + "explorer.exe /select, {2} ", + "{2}{5}" + ), + cmdKonsoleKDEKonqueror(4, "KDE Konsole / Konqueror", + "konsole --noclose --workdir {1}", + "konsole --noclose --workdir {1} -e ./''{3}''", + "konqueror file:\"{2}\"", + "{2}{5}" + ), + cmdKonsoleGnome(5, "Gnome Terminal / Nautilus", + "gnome-terminal --working-directory=\"{1}\"", + "gnome-terminal --working-directory=\"{1}\" --command=./''{3}''", + "nautilus {2}", + "{2}{5}" + ), + cmdXtermDtfile(6, "CDE Xterm / Dtfile", + "cd {1} && xterm", + "cd {1} && xterm -e ./''{3}''", + "cd {1} && dtfile", + "{2}{5}" + ), + cmdTerminalFinder(7, "MAC OS X Terminal / Finder", + "open -a Terminal {1}", + "open -a Terminal {2}", + "open -R {2}", + "{2}{5}" + ), + cmdKonsoleKDEDolphin(8, "KDE Konsole / Dolphin", + "konsole --workdir {1}", + "konsole --workdir {1} --noclose -e {2}", + "dolphin --select {2}", + "{2}{5}" + ), + cmdWinConsole(9, "Windows Console / Explorer", + "console.exe -w \"{4}\" -d {1}", + "console.exe -w \"{4}\" -d {1} -r \"/k\\\"{3}\\\"\"", + "explorer.exe /select, {2}", + "{2}{5}" + ), + cmdWinTotalCommander(10, "Windows DOS-Shell / TotalCommander", + "cmd.exe /C start \"{4}\" /D {1} cmd.exe /K", + "cmd.exe /C start \"{4}\" /D {1} {3}", + "totalcmd.exe /O /T {1}", + "{2}{5}" + ), + cmdWinGitBash(11, "Windows Git-Bash / Explorer", + "cmd.exe /C start \"{4}\" /D {1} \"C:\\Program Files (x86)\\Git\\bin\\bash.exe\" --login -i", + "cmd.exe /C start \"{4}\" /D {1} \"C:\\Program Files (x86)\\Git\\bin\\bash.exe\" --login -i -c ./''{3}''", + "explorer.exe /select, {2} ", + "{2}{5}" + ), + cmdWinConEmu(12, "Windows ConEmu / Explorer", + "ConEmu.exe /Title \"{4}\" /Dir \"{1}\" /Single /cmd cmd", + "ConEmu.exe /Title \"{4}\" /Dir \"{1}\" /Single /cmd \"{3}\"", + "explorer.exe /select, {2} ", + "{2}{5}" + ); + // attributes + private final int id; + private final String label; + private final String openCmd; + private final String runCmd; + private final String exploreCmd; + private final String copyPathCmd; + // construct + Command(int id, String label, String openCmd, String runCmd, String exploreCmd, String copyPathCmd) { + this.id = id; + this.label = label; + this.openCmd = openCmd; + this.runCmd = runCmd; + this.exploreCmd = exploreCmd; + this.copyPathCmd = copyPathCmd; + } + public int getId() { + return id; + } + public String getLabel() { + return label; + } + public String getOpenCmd() { + return openCmd; + } + public String getRunCmd() { + return runCmd; + } + public String getExploreCmd() { + return exploreCmd; + } + public String getCopyPathCmd() { + return copyPathCmd; + } + static Command getFromId(int id) { + Command ret = cmdUnknown; + for(int i = 0; i < Command.values().length; i++) { + if (Command.values()[i].getId() == id) { + ret = Command.values()[i]; + } + } + return ret; + } + } + + public PrefsV1_4() { + } + + /** + * Sets the default values of the preferences. + */ + private static void initializeDefaults(IPreferenceStore store) { + // get proper command (detect) + Command cmd = getProperCommand(); + // set default commands + store.setDefault(PreferenceEntry.preferenceTargetOpen.getString(), cmd.getOpenCmd()); + store.setDefault(PreferenceEntry.preferenceTargetRun.getString(), cmd.getRunCmd()); + store.setDefault(PreferenceEntry.preferenceTargetExplore.getString(), cmd.getExploreCmd()); + store.setDefault(PreferenceEntry.preferenceTargetCopyPath.getString(), cmd.getCopyPathCmd()); + // set default selected preset + store.setDefault(PreferenceEntry.preferenceListId.getString(), cmd.getId() - 1); + store.setDefault(PreferenceEntry.preferenceListString.getString(), cmd.name()); + // set default + store.setDefault(PreferenceEntry.preferenceQuotes.getString(), Quotes.quotesNo.name()); + store.setDefault(PreferenceEntry.preferenceDebug.getString(), Debug.debugNo.name()); + store.setDefault(PreferenceEntry.preferenceTokenizer.getString(), Tokenizer.EasyShellTokenizerYes.name()); + } + + public static List getPreferenceList() { + List list = new ArrayList(); + //list.add(PreferenceEntry.preferenceListId.getString()); + list.add(PreferenceEntry.preferenceListString.getString()); + list.add(PreferenceEntry.preferenceTargetOpen.getString()); + list.add(PreferenceEntry.preferenceTargetRun.getString()); + list.add(PreferenceEntry.preferenceTargetExplore.getString()); + list.add(PreferenceEntry.preferenceTargetCopyPath.getString()); + //list.add(PreferenceEntry.preferenceQuotes.getString()); + //list.add(PreferenceEntry.preferenceDebug.getString()); + //list.add(PreferenceEntry.preferenceTokenizer.getString()); + return list; + } + + /** + * Loads the preference store and sets the data to controls. + * + * @return store loaded. + */ + public static boolean loadStore(IPreferenceStore store, List cmdDataList, List menuDataList) { + // set defaults first + initializeDefaults(store); + // get the properties now + String IdStr = store.getString(PreferenceEntry.preferenceListString.getString()); + Command command = Command.valueOf(IdStr); + String openCmd = store.getString(PreferenceEntry.preferenceTargetOpen.getString()); + String runCmd = store.getString(PreferenceEntry.preferenceTargetRun.getString()); + String exploreCmd = store.getString(PreferenceEntry.preferenceTargetExplore.getString()); + String copyPathCmd = store.getString(PreferenceEntry.preferenceTargetCopyPath.getString()); + String QuotesStr = store.getString(PreferenceEntry.preferenceQuotes.getString()); + Quotes quotes = Quotes.valueOf(QuotesStr); + String DebugStr = store.getString(PreferenceEntry.preferenceDebug.getString()); + Debug debug = Debug.valueOf(DebugStr); + String TokenizerStr = store.getString(PreferenceEntry.preferenceTokenizer.getString()); + Tokenizer tokenizer = Tokenizer.valueOf(TokenizerStr); + return true; + } + + private static Command getProperCommand() { + Command cmd = Command.cmdUnknown; + /* possible OS string: + AIX + Digital UNIX + FreeBSD + HP UX + Irix + Linux + Mac OS + Mac OS X + MPE/iX + Netware 4.11 + OS/2 + Solaris + Windows 95 + Windows 98 + Windows NT + Windows Me + Windows 2000 + Windows XP + Windows 2003 + Windows CE + Windows Vista + Windows 7 + */ + String osname = System.getProperty("os.name", "").toLowerCase(); + if (osname.indexOf("windows") != -1) { + cmd = Command.cmdWinDOS; + } else if (osname.indexOf("mac os x") != -1) { + cmd = Command.cmdTerminalFinder; + } else if ( + osname.indexOf("unix") != -1 + || osname.indexOf("irix") != -1 + || osname.indexOf("freebsd") != -1 + || osname.indexOf("hp-ux") != -1 + || osname.indexOf("aix") != -1 + || osname.indexOf("sunos") != -1 + || osname.indexOf("linux") != -1 + ) + { + LinuxDesktop desktop = detectDesktopNew(); // old: detectDesktop() + if(desktop == LinuxDesktop.desktopKde) { + cmd = Command.cmdKonsoleKDEDolphin; + } else if(desktop == LinuxDesktop.desktopGnome) { + cmd = Command.cmdKonsoleGnome; + } else if(desktop == LinuxDesktop.desktopCde) { + cmd = Command.cmdXtermDtfile; + } + } + return cmd; + } + + private static LinuxDesktop detectDesktopNew() { + LinuxDesktop resultCode = LinuxDesktop.desktopUnknown; + if (isKDE()) { + resultCode = LinuxDesktop.desktopKde; + } else if (isGnome()) { + resultCode = LinuxDesktop.desktopGnome; + } + return resultCode; + } + + /** + * detects KDE desktop + * + * @see http://techbase.kde.org/KDE_System_Administration/Environment_Variables#KDE_FULL_SESSION + */ + private static boolean isKDE() { + boolean kde = false; + String[] cmd = new String[2]; + cmd [0] = "echo"; + cmd [1] = "$KDE_FULL_SESSION"; + kde = isExpectedCommandOutput(cmd, "true", true); + // if not found try another env + if (!kde) { + cmd [1] = "$DESKTOP_SESSION"; + kde = isExpectedCommandOutput(cmd, "kde", true); + } + return kde; + } + + /** + * detects Gnome desktop + */ + private static boolean isGnome() { + boolean gnome = false; + String[] cmd = new String[2]; + cmd [0] = "echo"; + cmd [1] = "$GNOME_DESKTOP_SESSION_ID"; + gnome = isExpectedCommandOutput(cmd, "*", true); + // if not found try another env + if (!gnome) { + cmd [1] = "$DESKTOP_SESSION"; + gnome = isExpectedCommandOutput(cmd, "gnome", true); + } + return gnome; + } + + /** + * Detects which desktop is used on a unix / linux system. + * + * @todo use regex + * + * @return The type of desktop. + * @see detectDesktop + */ + private static boolean isExpectedCommandOutput(String[] command, String expectedOutput, boolean toLowerCase) { + boolean found = false; + try { + Process proc = Runtime.getRuntime().exec(command); + BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream())); + String line = null; + while((line = in.readLine()) != null && !found) { + // in case of * just something should be returned + if (expectedOutput.indexOf("*") != -1) + { + if (line.isEmpty()) { + found = false; + break; + } else { + found = true; + } + } else { + if (toLowerCase) + line = line.toLowerCase(); + if(line.indexOf(expectedOutput) != -1) { + found = true; + } + } + } + BufferedReader err = new BufferedReader(new InputStreamReader(proc.getErrorStream())); + line = null; + // If there is any error output, print it to + // stdout for debugging purposes + while((line = err.readLine()) != null) { + //EasyShellPlugin.getDefault().sysout(true, "detectDesktop stderr >" + line + "<"); + } + + int result = proc.waitFor(); + if(result != 0) { + // If there is any error code, print it to + // stdout for debugging purposes + //EasyShellPlugin.getDefault().sysout(true, "detectDesktop return code: " + result); + } + } catch(Exception e) { + e.printStackTrace(); + } + return found; + } + +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/PrefsV1_5.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/PrefsV1_5.java new file mode 100644 index 00000000..af2d1e16 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/PrefsV1_5.java @@ -0,0 +1,475 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.legacy; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.jface.preference.IPreferenceStore; + +import de.anbos.eclipse.easyshell.plugin.preferences.CommandData; +import de.anbos.eclipse.easyshell.plugin.preferences.MenuData; + +public class PrefsV1_5 { + + /** + * Commands. + */ + public enum Command { + cmdUnknown(0, "Unknown", "shell", "file browser", null, + "open ${easyshell:container_loc}", + "cd ${easyshell:container_loc} && run ./''${easyshell:resource_name}''", + "explore ${easyshell:resource_loc}", + "\"${easyshell:resource_loc}\"${easyshell:line_separator}" + ), + cmdWinDOS(1, "Windows", "DOS-Shell", "Explorer", null, + "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} cmd.exe /K", + "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} ${easyshell:resource_name}", + "explorer.exe /select, ${easyshell:resource_loc}", + "\"${easyshell:resource_loc}\"${easyshell:line_separator}" + ), + cmdWinPower(2, "Windows", "PowerShell", "Explorer", null, + "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} powershell.exe", + "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} powershell.exe -command ./''${easyshell:resource_name}''", + "explorer.exe /select, ${easyshell:resource_loc}", + "\"${easyshell:resource_loc}\"${easyshell:line_separator}" + ), + cmdWinCyg(3, "Windows", "Cygwin (Bash)", "Explorer", null, + "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Cygwin\\bin\\bash.exe\"", + "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Cygwin\\bin\\bash.exe\" -c ./''${easyshell:resource_name}''", + "explorer.exe /select, ${easyshell:resource_loc} ", + "\"${easyshell:resource_loc}\"${easyshell:line_separator}" + ), + cmdKonsoleKDEKonqueror(4, "Linux", "KDE Konsole", "Konqueror", null, + "konsole --noclose --workdir ${easyshell:container_loc}", + "konsole --noclose --workdir ${easyshell:container_loc} -e ./''${easyshell:resource_name}''", + "konqueror file:\"${easyshell:resource_loc}\"", + "${easyshell:resource_loc}${easyshell:line_separator}" + ), + cmdKonsoleGnome(5, "Linux", "Gnome Terminal", "Nautilus", null, + "gnome-terminal --working-directory=${easyshell:container_loc}", + "gnome-terminal --working-directory=${easyshell:container_loc} --command=./''${easyshell:resource_name}''", + "nautilus ${easyshell:resource_loc}", + "${easyshell:resource_loc}${easyshell:line_separator}" + ), + cmdXtermDtfile(6, "Linux" , "CDE Xterm", "Dtfile", null, + "cd ${easyshell:container_loc} && xterm", + "cd ${easyshell:container_loc} && xterm -e ./''${easyshell:resource_name}''", + "cd ${easyshell:container_loc} && dtfile", + "${easyshell:resource_loc}${easyshell:line_separator}" + ), + cmdTerminalFinder(7, "MAC OS X", "Terminal", "Finder", null, + "open -a Terminal ${easyshell:container_loc}", + "open -a Terminal ${easyshell:resource_loc}", + "open -R ${easyshell:resource_loc}", + "${easyshell:resource_loc}${easyshell:line_separator}" + ), + cmdKonsoleKDEDolphin(8, "Linux" , "KDE Konsole", "Dolphin", null, + "konsole --workdir ${easyshell:container_loc}", + "konsole --workdir ${easyshell:container_loc} --noclose -e ${easyshell:resource_loc}", + "dolphin --select ${easyshell:resource_loc}", + "${easyshell:resource_loc}${easyshell:line_separator}" + ), + cmdWinConsole(9, "Windows", "Console", "Explorer", null, + "console.exe -w \"${easyshell:project_name}\" -d ${easyshell:container_loc}", + "console.exe -w \"${easyshell:project_name}\" -d ${easyshell:container_loc} -r \"/k\\\"${easyshell:resource_name}\\\"\"", + "explorer.exe /select, ${easyshell:resource_loc}", + "\"${easyshell:resource_loc}\"${easyshell:line_separator}" + ), + cmdWinTotalCommander(10, "Windows", "DOS-Shell", "TotalCommander", null, + "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} cmd.exe /K", + "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} ${easyshell:resource_name}", + "totalcmd.exe /O /T ${easyshell:container_loc}", + "\"${easyshell:resource_loc}\"${easyshell:line_separator}" + ), + cmdWinGitBash(11, "Windows", "Git-Bash", "Explorer", null, + "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Program Files (x86)\\Git\\bin\\bash.exe\" --login -i", + "cmd.exe /C start \"${easyshell:project_name}\" /D ${easyshell:container_loc} \"C:\\Program Files (x86)\\Git\\bin\\bash.exe\" --login -i -c ./''${easyshell:resource_name}''", + "explorer.exe /select, ${easyshell:resource_loc} ", + "\"${easyshell:resource_loc}\"${easyshell:line_separator}" + ), + cmdWinConEmu(12, "Windows", "ConEmu", "Explorer", null, + "ConEmu.exe /Title \"${easyshell:project_name}\" /Dir \"${easyshell:container_loc}\" /Single /cmd cmd", + "ConEmu.exe /Title \"${easyshell:project_name}\" /Dir \"${easyshell:container_loc}\" /Single /cmd \"${easyshell:resource_name}\"", + "explorer.exe /select, ${easyshell:resource_loc} ", + "\"${easyshell:resource_loc}\"${easyshell:line_separator}" + ), + // https://sourceforge.net/p/pluginbox/feature-requests/18/ + // https://github.com/anb0s/EasyShell/issues/17 + cmdGnomeTermNemo(13, "Linux", "Gnome Terminal", "Nemo", null, + "gnome-terminal --working-directory=${easyshell:container_loc}", + "gnome-terminal --working-directory=${easyshell:container_loc} --command=./''${easyshell:resource_name}''", + "nemo ${easyshell:resource_loc}", + "${easyshell:resource_loc}${easyshell:line_separator}" + ), + // https://sourceforge.net/p/pluginbox/feature-requests/24/ + // https://github.com/anb0s/EasyShell/issues/23 + cmdGnomeTermThunar(14, "Linux", "Gnome Terminal", "Thunar", null, + "gnome-terminal --working-directory=${easyshell:container_loc}", + "gnome-terminal --working-directory=${easyshell:container_loc} --command=./''${easyshell:resource_name}''", + "thunar ${easyshell:container_loc}", + "${easyshell:resource_loc}${easyshell:line_separator}" + ), + // https://sourceforge.net/p/pluginbox/feature-requests/22/ + // https://github.com/anb0s/EasyShell/issues/21 + cmdXfceTermThunar(15, "Linux", "Xfce Terminal", "Thunar", null, + "xfce4-terminal --working-directory=${easyshell:container_loc}", + "xfce4-terminal --working-directory=${easyshell:container_loc} --command=./''${easyshell:resource_name}'' --hold", + "thunar ${easyshell:container_loc}", + "${easyshell:resource_loc}${easyshell:line_separator}" + ); + // attributes + private final int id; + private final String os; + private final String console; + private final String explorer; + private final String label; + private final String openCmd; + private final String runCmd; + private final String exploreCmd; + private final String copyPathCmd; + // construct + Command(int id, String os, String console, String explorer, String label, String openCmd, String runCmd, String exploreCmd, String copyPathCmd) { + this.id = id; + this.os = os; + this.console = console; + this.explorer = explorer; + if (label != null) { + this.label = label; + } else { + this.label = os + " " + console + " / " + explorer; + } + this.openCmd = openCmd; + this.runCmd = runCmd; + this.exploreCmd = exploreCmd; + this.copyPathCmd = copyPathCmd; + } + public int getId() { + return id; + } + public String getOS() { + return os; + } + public String getConsole() { + return console; + } + public String getExplorer() { + return explorer; + } + public String getLabel() { + return label; + } + public String getOpenCmd() { + return openCmd; + } + public String getRunCmd() { + return runCmd; + } + public String getExploreCmd() { + return exploreCmd; + } + public String getCopyPathCmd() { + return copyPathCmd; + } + public static Command getFromId(int id) { + Command ret = cmdUnknown; + for(int i = 0; i < Command.values().length; i++) { + if (Command.values()[i].getId() == id) { + ret = Command.values()[i]; + } + } + return ret; + } + } + + /** + * Constructs the preference page. + */ + public PrefsV1_5() { + } + + /** + * Sets the default values of the preferences. + */ + public static void initializeDefaults(IPreferenceStore store, int instId) { + // get proper command (detect) + Command cmd = getProperCommand(); + // set default commands + store.setDefault(PreferenceEntry.preferenceTargetEnabled.getString(instId), false); + store.setDefault(PreferenceEntry.preferenceTargetOpen.getString(instId), cmd.getOpenCmd()); + store.setDefault(PreferenceEntry.preferenceTargetRun.getString(instId), cmd.getRunCmd()); + store.setDefault(PreferenceEntry.preferenceTargetExplore.getString(instId), cmd.getExploreCmd()); + store.setDefault(PreferenceEntry.preferenceTargetCopyPath.getString(instId), cmd.getCopyPathCmd()); + // set default selected preset + store.setDefault(PreferenceEntry.preferenceListId.getString(instId), cmd.getId() - 1); + store.setDefault(PreferenceEntry.preferenceListString.getString(instId), cmd.name()); + // set default + store.setDefault(PreferenceEntry.preferenceQuotes.getString(instId), Quotes.quotesNo.name()); + store.setDefault(PreferenceEntry.preferenceDebug.getString(instId), Debug.debugNo.name()); + store.setDefault(PreferenceEntry.preferenceTokenizer.getString(instId), Tokenizer.EasyShellTokenizerYes.name()); + } + + public static List getPreferenceList() { + List list = new ArrayList(); + list.add(PreferenceEntry.preferenceTargetEnabled.getString()); + //list.add(PreferenceEntry.preferenceListId.getString()); + list.add(PreferenceEntry.preferenceListString.getString()); + list.add(PreferenceEntry.preferenceTargetOpen.getString()); + list.add(PreferenceEntry.preferenceTargetRun.getString()); + list.add(PreferenceEntry.preferenceTargetExplore.getString()); + list.add(PreferenceEntry.preferenceTargetCopyPath.getString()); + //list.add(PreferenceEntry.preferenceQuotes.getString()); + //list.add(PreferenceEntry.preferenceDebug.getString()); + //list.add(PreferenceEntry.preferenceTokenizer.getString()); + return list; + } + + /** + * Loads the preference store and sets the data to controls. + * + * @return store loaded. + */ + public static boolean loadStore(IPreferenceStore store, List cmdDataList, List menuDataList) { + /* + DebugStr=debugYes + DebugStr1=debugNo + DebugStr2=debugNo + IdStr1=cmdWinPower + IdStr2=cmdWinCyg + QuotesStr=quotesAuto + QuotesStr1=quotesNo + QuotesStr2=quotesNo + TokenizerStr=EasyShellTokenizerNo + TokenizerStr1=EasyShellTokenizerYes + TokenizerStr2=EasyShellTokenizerYes + eclipse.preferences.version=1 + listPreference1=1 + listPreference2=2 + targetCopyPathPreference={2}{5} copy + targetEnabled=true + targetEnabled1=true + targetEnabled2=true + targetExplorePreference=explorer.exe /select, {2} my + targetExplorePreference2=explorer.exe /select, ${easyshell\:resource_loc} + targetPreference=cmd.exe /C start "{4}" /D {1} cmd.exe /K test + targetPreference1=cmd.exe /C start "${easyshell\:project_name}" /D ${easyshell\:container_loc} powershell.exe + targetPreference2=cmd.exe /C start "${easyshell\:project_name}" /D ${easyshell\:container_loc} "C\:\\Cygwin\\bin\\bash.exe" + targetRunPreference=cmd.exe /C start "{4}" /D {1} {3} hello + targetRunPreference1=cmd.exe /C start "${easyshell\:project_name}" /D ${easyshell\:container_loc} powershell.exe -command ./''${easyshell\:resource_name}'' + targetRunPreference2=cmd.exe /C start "${easyshell\:project_name}" /D ${easyshell\:container_loc} "C\:\\Cygwin\\bin\\bash.exe" -c ./''${easyshell\:resource_name}'' + */ + for (int instanceId=0;instanceId<3;instanceId++) { + // set defaults first + initializeDefaults(store, instanceId); + // get the properties now + if (store.getBoolean(PreferenceEntry.preferenceTargetEnabled.getString(instanceId))) { + String IdStr = store.getString(PreferenceEntry.preferenceListString.getString(instanceId)); + Command command = Command.valueOf(IdStr); + String openCmd = store.getString(PreferenceEntry.preferenceTargetOpen.getString(instanceId)); + String runCmd = store.getString(PreferenceEntry.preferenceTargetRun.getString(instanceId)); + String exploreCmd = store.getString(PreferenceEntry.preferenceTargetExplore.getString(instanceId)); + String copyPathCmd = store.getString(PreferenceEntry.preferenceTargetCopyPath.getString(instanceId)); + String QuotesStr = store.getString(PreferenceEntry.preferenceQuotes.getString(instanceId)); + Quotes quotes = Quotes.valueOf(QuotesStr); + String DebugStr = store.getString(PreferenceEntry.preferenceDebug.getString(instanceId)); + Debug debug = Debug.valueOf(DebugStr); + String TokenizerStr = store.getString(PreferenceEntry.preferenceTokenizer.getString(instanceId)); + Tokenizer tokenizer = Tokenizer.valueOf(TokenizerStr); + } + } + return true; + } + + private static Command getProperCommand() { + Command cmd = Command.cmdUnknown; + /* possible OS string: + AIX + Digital UNIX + FreeBSD + HP UX + Irix + Linux + Mac OS + Mac OS X + MPE/iX + Netware 4.11 + OS/2 + Solaris + Windows 95 + Windows 98 + Windows NT + Windows Me + Windows 2000 + Windows XP + Windows 2003 + Windows CE + Windows Vista + Windows 7 + */ + String osname = System.getProperty("os.name", "").toLowerCase(); + if (osname.indexOf("windows") != -1) { + cmd = Command.cmdWinDOS; + } else if (osname.indexOf("mac os x") != -1) { + cmd = Command.cmdTerminalFinder; + } else if ( + osname.indexOf("unix") != -1 + || osname.indexOf("irix") != -1 + || osname.indexOf("freebsd") != -1 + || osname.indexOf("hp-ux") != -1 + || osname.indexOf("aix") != -1 + || osname.indexOf("sunos") != -1 + || osname.indexOf("linux") != -1 + ) + { + // try to detect the desktop + LinuxDesktop desktop = detectLinuxDesktop(); + //Activator.getDefault().sysout(true, "Detected linux (Unix) desktop: >" + desktop.getName() + "<"); + switch (desktop) { + case desktopKde: cmd = Command.cmdKonsoleKDEDolphin; break; + case desktopCinnamon: cmd = Command.cmdGnomeTermNemo; break; + case desktopGnome: cmd = Command.cmdKonsoleGnome; break; + case desktopCde: cmd = Command.cmdXtermDtfile; break; + case desktopXfce: cmd = Command.cmdXfceTermThunar; break; + default: cmd = Command.cmdUnknown; + } + // try to detect the default file browser + if (desktop != LinuxDesktop.desktopUnknown) { + String fileBrowser = detectLinuxDefaultFileBrowser(); + //Activator.getDefault().sysout(true, "Detected linux (Unix) default file browser: >" + fileBrowser + "<"); + } + } + return cmd; + } + + private static LinuxDesktop detectLinuxDesktop() { + LinuxDesktop resultCode = detectDesktopSession(); + if (resultCode == LinuxDesktop.desktopUnknown) + { + if (isCde()) + resultCode = LinuxDesktop.desktopCde; + } + return resultCode; + } + + /** + * detects desktop from $DESKTOP_SESSION + */ + private static LinuxDesktop detectDesktopSession() { + ArrayList command = new ArrayList(); + command.add("sh"); + command.add("-c"); + command.add("echo \"$DESKTOP_SESSION\""); + // fill the map + Map desktops = new HashMap(); + desktops.put("kde", LinuxDesktop.desktopKde); + desktops.put("gnome", LinuxDesktop.desktopGnome); + desktops.put("cinnamon", LinuxDesktop.desktopCinnamon); + desktops.put("xfce", LinuxDesktop.desktopXfce); + // execute + String desktop = isExpectedCommandOutput(command, desktops, true); + if (desktop != null && !desktop.isEmpty()) { + return (LinuxDesktop)desktops.get(desktop); + } + return LinuxDesktop.desktopUnknown; + } + + /** + * TODO: detects CDE desktop + */ + private static boolean isCde() { + return false; + } + + /** + * detects programs from $DESKTOP_SESSION + */ + private static String detectLinuxDefaultFileBrowser() { + ArrayList command = new ArrayList(); + command.add("xdg-mime"); + command.add("query"); + command.add("default"); + command.add("inode/directory"); + // fill the map + Map fileBrowsers = new HashMap(); + fileBrowsers.put("nemo.desktop", "nemo"); + // execute + String fileBrowser = isExpectedCommandOutput(command, fileBrowsers, true); + if (fileBrowser != null && !fileBrowser.isEmpty()) { + return (String)fileBrowsers.get(fileBrowser); + } + return null; + } + + /** + * Detects which desktop is used on a unix / linux system. + * + * @todo use regex + * + * @return The type of desktop. + * @see detectDesktop + */ + private static String isExpectedCommandOutput(ArrayList command, Map expectedOutput, boolean toLowerCase) { + boolean found = false; + String expectedLine = null; + try { + Process proc = Runtime.getRuntime().exec(command.toArray(new String[1])); + BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream())); + String line = null; + while((line = in.readLine()) != null && !found) { + for(String key: expectedOutput.keySet()) { + // in case of * just something should be returned + if (key.indexOf("*") != -1) + { + if (line.isEmpty()) { + found = false; + break; + } else { + found = true; + } + } else { + if (toLowerCase) + line = line.toLowerCase(); + if(line.indexOf(key) != -1) { + found = true; + } + } + if (found) { + expectedLine = line; + break; + } + } + } + line = null; + BufferedReader err = new BufferedReader(new InputStreamReader(proc.getErrorStream())); + // If there is any error output, print it to + // stdout for debugging purposes + while((line = err.readLine()) != null) { + //Activator.getDefault().sysout(true, "detectDesktop stderr >" + line + "<"); + } + + int result = proc.waitFor(); + if(result != 0) { + // If there is any error code, print it to + // stdout for debugging purposes + //Activator.getDefault().sysout(true, "detectDesktop return code: " + result); + } + } catch(Exception e) { + e.printStackTrace(); + } + return expectedLine; + } + +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/Quotes.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/Quotes.java new file mode 100644 index 00000000..4b5853a8 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/Quotes.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.legacy; + +/** + * Quotes. + */ +public enum Quotes { + quotesNo(0, "No"), + quotesSingle(1, "Single"), + quotesDouble(2, "Double"), + quotesAuto(3, "Double (automatic)"), // check if no quotes and space in string, then add + quotesAutoSingle(4, "Single (automatic)"), // check if no quotes and space in string, then add + quotesEscape(5, "Escape"); // check if no quotes and space in string, then escape + // attributes + private final int id; + private final String mode; + // construct + Quotes(int id, String mode) { + this.id = id; + this.mode = mode; + } + public int getId() { + return id; + } + public String getMode() { + return mode; + } + public static Quotes getFromId(int id) { + Quotes ret = quotesNo; + for(int i = 0; i < Quotes.values().length; i++) { + if (Quotes.values()[i].getId() == id) { + ret = Quotes.values()[i]; + } + } + return ret; + } +} \ No newline at end of file diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/Tokenizer.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/Tokenizer.java new file mode 100644 index 00000000..6c45e05d --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/Tokenizer.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.legacy; + +/** + * Tokenizer. + */ +public enum Tokenizer { + EasyShellTokenizerNo(0, "No"), + EasyShellTokenizerYes(1, "Yes"); + // attributes + private final int id; + private final String mode; + // construct + Tokenizer(int id, String mode) { + this.id = id; + this.mode = mode; + } + public int getId() { + return id; + } + public String getMode() { + return mode; + } + public static Tokenizer getFromId(int id) { + Tokenizer ret = EasyShellTokenizerYes; + for(int i = 0; i < Tokenizer.values().length; i++) { + if (Tokenizer.values()[i].getId() == id) { + ret = Tokenizer.values()[i]; + } + } + return ret; + } +}; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java index 3c4c4ab4..1df4560c 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java @@ -12,18 +12,19 @@ package de.anbos.eclipse.easyshell.plugin.preferences; import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; import org.eclipse.jface.dialogs.MessageDialog; -//import org.eclipse.core.runtime.preferences.IEclipsePreferences; -//import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.jface.preference.IPreferenceStore; -//import org.osgi.service.prefs.BackingStoreException; -//import org.osgi.service.prefs.Preferences; import de.anbos.eclipse.easyshell.plugin.Activator; import de.anbos.eclipse.easyshell.plugin.Constants; import de.anbos.eclipse.easyshell.plugin.Utils; +import de.anbos.eclipse.easyshell.plugin.legacy.PrefsV1_4; +import de.anbos.eclipse.easyshell.plugin.legacy.PrefsV1_5; import de.anbos.eclipse.easyshell.plugin.types.Version; public class Initializer extends AbstractPreferenceInitializer { @@ -35,17 +36,6 @@ public void initializeDefaultPreferences() { setDefaults(store); // migrate from old store migrate(store); - /* - IEclipsePreferences instanceNode = InstanceScope.INSTANCE.getNode(Activator.PLUGIN_ID); - Preferences preferences = instanceNode.node(Constants.PREF_VERSIONS[0]); - preferences.put("test", "value"); - try { - preferences.flush(); - } catch (BackingStoreException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - */ } private void setDefaults(IPreferenceStore store) { @@ -103,25 +93,31 @@ private void migrate(IPreferenceStore store) { private int migrate_from_v2(IPreferenceStore store, Version version, int migrateState) { // get the old v2 store - IPreferenceStore oldStore = Activator.getDefault().getNewPreferenceStoreByVersion(version.name()); + IPreferenceStore oldStore = Activator.getDefault().getPreferenceStoreByVersion(version.name()); // check preferences for default values - migrateState = migrate_check_pref_and_ask_user(oldStore, version, Constants.PREF_COMMANDS, migrateState); + migrateState = migrate_check_pref_and_ask_user(oldStore, version, new ArrayList(Arrays.asList(Constants.PREF_COMMANDS)), migrateState); if (migrateState == 0) { store.setValue(Constants.PREF_COMMANDS, PreferenceValueConverter.migrateCommandDataList(version, oldStore.getString(Constants.PREF_COMMANDS))); } - migrateState = migrate_check_pref_and_ask_user(oldStore, version, Constants.PREF_MENU, migrateState); + migrateState = migrate_check_pref_and_ask_user(oldStore, version, new ArrayList(Arrays.asList(Constants.PREF_MENU)), migrateState); if (migrateState == 0) { store.setValue(Constants.PREF_MENU, PreferenceValueConverter.migrateMenuDataList(version, oldStore.getString(Constants.PREF_MENU))); } return migrateState; } - private int migrate_check_pref_and_ask_user(IPreferenceStore store, Version version, String pref, int migrateState) { + private int migrate_check_pref_and_ask_user(IPreferenceStore store, Version version, List prefList, int migrateState) { // if cancel or no just skip this time if (migrateState == 1 || migrateState == 2) { return migrateState; } - boolean migrationPossible = !store.isDefault(pref); + boolean migrationPossible = false; + for (String pref : prefList) { + if (!store.isDefault(pref)) { + migrationPossible = true; + break; + } + } if (migrationPossible) { // ask user if not already asked and said yes if (migrateState != 0) { @@ -141,8 +137,31 @@ private int migrate_check_pref_and_ask_user(IPreferenceStore store, Version vers } private int migrate_from_v1(IPreferenceStore store, Version version, int migrateState) { - // TODO: - return -1; + // get the old v1_5 store + IPreferenceStore oldStore = Activator.getDefault().getLegacyPreferenceStore(); + // check if we want version 1.5 or 1.4 + if (version == Version.v1_5) { + // check preferences for default values + migrateState = migrate_check_pref_and_ask_user(oldStore, version, PrefsV1_5.getPreferenceList(), migrateState); + if (migrateState == 0) { + List cmdDataList = new ArrayList(); + List menuDataList = new ArrayList(); + if (PrefsV1_5.loadStore(oldStore, cmdDataList, menuDataList)) { + store.setValue(Constants.PREF_COMMANDS, PreferenceValueConverter.asCommandDataString(cmdDataList)); + store.setValue(Constants.PREF_MENU, PreferenceValueConverter.asMenuDataString(menuDataList)); + } + } + } else if (version == Version.v1_4) { + // check preferences for default values + migrateState = migrate_check_pref_and_ask_user(oldStore, version, PrefsV1_4.getPreferenceList(), migrateState); + List cmdDataList = new ArrayList(); + List menuDataList = new ArrayList(); + if (PrefsV1_4.loadStore(oldStore, cmdDataList, menuDataList)) { + store.setValue(Constants.PREF_COMMANDS, PreferenceValueConverter.asCommandDataString(cmdDataList)); + store.setValue(Constants.PREF_MENU, PreferenceValueConverter.asMenuDataString(menuDataList)); + } + } + return migrateState; } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Version.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Version.java index b8afdac6..09b29928 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Version.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Version.java @@ -18,10 +18,12 @@ public enum Version { // do not delete any versions and append new versions! vUnknown(-1, "Unknown"), v1_4(0, "v1.4.x"), - v2_0_001(1, "v2.0 beta 1"), - v2_0_002(2, "v2.0 beta 2"), - v2_0_003(3, "v2.0 beta 3"), - v2_0_004(4, "v2.0 bata 4"); + v1_5(1, "v1.5.x"), + v2_0_001(2, "v2.0 beta 1"), + v2_0_002(3, "v2.0 beta 2"), + v2_0_003(4, "v2.0 beta 3"), + v2_0_004(5, "v2.0 beta 4"), + v2_0_005(6, "v2.0 RC1"); // actual version is always the last one! public static Version actual = Version.values()[Version.values().length-1]; // attributes From 448255030041bb4cf98100cc46fbdabb25f89d47 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Mon, 5 Sep 2016 10:49:55 +0200 Subject: [PATCH 46/73] #55 [v2.0] migration support from legacy EasyShell v1.x Signed-off-by: Andre Bossert --- .../plugin/commands/DefineCommands.java | 3 +- .../easyshell/plugin/legacy/PrefsV1_4.java | 124 +++++++++++++++--- .../easyshell/plugin/legacy/PrefsV1_5.java | 83 ++++++++++-- .../plugin/preferences/CommandData.java | 26 ++-- .../CommandDataDefaultCollection.java | 55 +++----- .../plugin/preferences/CommandDataList.java | 37 ++++++ .../plugin/preferences/CommandDataStore.java | 13 +- .../plugin/preferences/CommandPage.java | 2 +- .../easyshell/plugin/preferences/Data.java | 9 +- .../plugin/preferences/DataStore.java | 1 + .../plugin/preferences/Initializer.java | 14 +- .../plugin/preferences/MenuData.java | 16 ++- .../plugin/preferences/MenuDataList.java | 37 ++++++ .../plugin/preferences/MenuDataStore.java | 14 +- .../plugin/preferences/MenuPage.java | 2 +- .../easyshell/plugin/types/MenuNameType.java | 11 +- 16 files changed, 330 insertions(+), 117 deletions(-) create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataList.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataList.java diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java index 4abf8363..20b330d7 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java @@ -25,6 +25,7 @@ import de.anbos.eclipse.easyshell.plugin.Activator; import de.anbos.eclipse.easyshell.plugin.preferences.CommandDataStore; import de.anbos.eclipse.easyshell.plugin.preferences.MenuData; +import de.anbos.eclipse.easyshell.plugin.preferences.MenuDataList; import de.anbos.eclipse.easyshell.plugin.preferences.MenuDataStore; public class DefineCommands extends ExtensionContributionFactory { @@ -39,7 +40,7 @@ public void createContributionItems(IServiceLocator serviceLocator, // load the preferences CommandDataStore.instance().load(); MenuDataStore.instance().load(); - List items = MenuDataStore.instance().getEnabledCommandMenuDataList(); + MenuDataList items = MenuDataStore.instance().getEnabledCommandMenuDataList(); for (MenuData item : items) { addItem(serviceLocator, additions, item.getNameExpanded(), diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/PrefsV1_4.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/PrefsV1_4.java index eb17f5fc..4d02a52e 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/PrefsV1_4.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/PrefsV1_4.java @@ -18,9 +18,17 @@ import org.eclipse.jface.preference.IPreferenceStore; -import de.anbos.eclipse.easyshell.plugin.legacy.PrefsV1_5.Command; import de.anbos.eclipse.easyshell.plugin.preferences.CommandData; +import de.anbos.eclipse.easyshell.plugin.preferences.CommandDataList; import de.anbos.eclipse.easyshell.plugin.preferences.MenuData; +import de.anbos.eclipse.easyshell.plugin.preferences.MenuDataList; +import de.anbos.eclipse.easyshell.plugin.types.Category; +import de.anbos.eclipse.easyshell.plugin.types.CommandType; +import de.anbos.eclipse.easyshell.plugin.types.MenuNameType; +import de.anbos.eclipse.easyshell.plugin.types.OS; +import de.anbos.eclipse.easyshell.plugin.types.PresetType; +import de.anbos.eclipse.easyshell.plugin.types.ResourceType; +import de.anbos.eclipse.easyshell.plugin.types.Version; public class PrefsV1_4 { @@ -28,79 +36,79 @@ public class PrefsV1_4 { * Commands. */ private enum Command { - cmdUnknown(0, "Unknown shell / file browser", + cmdUnknown(0, "Unknown", "shell", "file browser", null, "open {1}", "cd {1} && run ./''{3}''", "explore {2}", "{2}{5}" ), - cmdWinDOS(1, "Windows DOS-Shell / Explorer", + cmdWinDOS(1, "Windows", "DOS-Shell", "Explorer", null, "cmd.exe /C start \"{4}\" /D {1} cmd.exe /K", "cmd.exe /C start \"{4}\" /D {1} {3}", "explorer.exe /select, {2}", "{2}{5}" ), - cmdWinPower(2, "Windows PowerShell / Explorer", + cmdWinPower(2, "Windows", "PowerShell", "Explorer", null, "cmd.exe /C start \"{4}\" /D {1} powershell.exe", "cmd.exe /C start \"{4}\" /D {1} powershell.exe -command ./''{3}''", "explorer.exe /select, {2}", "{2}{5}" ), - cmdWinCyg(3, "Windows Cygwin (Bash) / Explorer", + cmdWinCyg(3, "Windows", "Cygwin (Bash)", "Explorer", null, "cmd.exe /C start \"{4}\" /D {1} \"C:\\Cygwin\\bin\\bash.exe\"", "cmd.exe /C start \"{4}\" /D {1} \"C:\\Cygwin\\bin\\bash.exe\" -c ./''{3}''", "explorer.exe /select, {2} ", "{2}{5}" ), - cmdKonsoleKDEKonqueror(4, "KDE Konsole / Konqueror", + cmdKonsoleKDEKonqueror(4, "Linux", "KDE Konsole", "Konqueror", null, "konsole --noclose --workdir {1}", "konsole --noclose --workdir {1} -e ./''{3}''", "konqueror file:\"{2}\"", "{2}{5}" ), - cmdKonsoleGnome(5, "Gnome Terminal / Nautilus", + cmdKonsoleGnome(5, "Linux", "Gnome Terminal", "Nautilus", null, "gnome-terminal --working-directory=\"{1}\"", "gnome-terminal --working-directory=\"{1}\" --command=./''{3}''", "nautilus {2}", "{2}{5}" ), - cmdXtermDtfile(6, "CDE Xterm / Dtfile", + cmdXtermDtfile(6, "Linux", "CDE Xterm", "Dtfile", null, "cd {1} && xterm", "cd {1} && xterm -e ./''{3}''", "cd {1} && dtfile", "{2}{5}" ), - cmdTerminalFinder(7, "MAC OS X Terminal / Finder", + cmdTerminalFinder(7, "MAC OS X", "Terminal", "Finder", null, "open -a Terminal {1}", "open -a Terminal {2}", "open -R {2}", "{2}{5}" ), - cmdKonsoleKDEDolphin(8, "KDE Konsole / Dolphin", + cmdKonsoleKDEDolphin(8, "Linux", "KDE Konsole", "Dolphin", null, "konsole --workdir {1}", "konsole --workdir {1} --noclose -e {2}", "dolphin --select {2}", "{2}{5}" ), - cmdWinConsole(9, "Windows Console / Explorer", + cmdWinConsole(9, "Windows", "Console", "Explorer", null, "console.exe -w \"{4}\" -d {1}", "console.exe -w \"{4}\" -d {1} -r \"/k\\\"{3}\\\"\"", "explorer.exe /select, {2}", "{2}{5}" ), - cmdWinTotalCommander(10, "Windows DOS-Shell / TotalCommander", + cmdWinTotalCommander(10, "Windows", "DOS-Shell", "TotalCommander", null, "cmd.exe /C start \"{4}\" /D {1} cmd.exe /K", "cmd.exe /C start \"{4}\" /D {1} {3}", "totalcmd.exe /O /T {1}", "{2}{5}" ), - cmdWinGitBash(11, "Windows Git-Bash / Explorer", + cmdWinGitBash(11, "Windows", "Git-Bash", "Explorer", null, "cmd.exe /C start \"{4}\" /D {1} \"C:\\Program Files (x86)\\Git\\bin\\bash.exe\" --login -i", "cmd.exe /C start \"{4}\" /D {1} \"C:\\Program Files (x86)\\Git\\bin\\bash.exe\" --login -i -c ./''{3}''", "explorer.exe /select, {2} ", "{2}{5}" ), - cmdWinConEmu(12, "Windows ConEmu / Explorer", + cmdWinConEmu(12, "Windows", "ConEmu", "Explorer", null, "ConEmu.exe /Title \"{4}\" /Dir \"{1}\" /Single /cmd cmd", "ConEmu.exe /Title \"{4}\" /Dir \"{1}\" /Single /cmd \"{3}\"", "explorer.exe /select, {2} ", @@ -108,15 +116,25 @@ private enum Command { ); // attributes private final int id; + private final String os; + private final String console; + private final String explorer; private final String label; private final String openCmd; private final String runCmd; private final String exploreCmd; private final String copyPathCmd; // construct - Command(int id, String label, String openCmd, String runCmd, String exploreCmd, String copyPathCmd) { + Command(int id, String os, String console, String explorer, String label, String openCmd, String runCmd, String exploreCmd, String copyPathCmd) { this.id = id; - this.label = label; + this.os = os; + this.console = console; + this.explorer = explorer; + if (label != null) { + this.label = label; + } else { + this.label = os + " " + console + " / " + explorer; + } this.openCmd = openCmd; this.runCmd = runCmd; this.exploreCmd = exploreCmd; @@ -125,6 +143,15 @@ private enum Command { public int getId() { return id; } + public String getOS() { + return os; + } + public String getConsole() { + return console; + } + public String getExplorer() { + return explorer; + } public String getLabel() { return label; } @@ -157,9 +184,7 @@ public PrefsV1_4() { /** * Sets the default values of the preferences. */ - private static void initializeDefaults(IPreferenceStore store) { - // get proper command (detect) - Command cmd = getProperCommand(); + private static void initializeDefaults(IPreferenceStore store, Command cmd) { // set default commands store.setDefault(PreferenceEntry.preferenceTargetOpen.getString(), cmd.getOpenCmd()); store.setDefault(PreferenceEntry.preferenceTargetRun.getString(), cmd.getRunCmd()); @@ -193,25 +218,82 @@ public static List getPreferenceList() { * * @return store loaded. */ - public static boolean loadStore(IPreferenceStore store, List cmdDataList, List menuDataList) { + public static boolean loadStore(IPreferenceStore store, OS os, CommandDataList cmdDataList, MenuDataList menuDataList) { + // get proper command (detect) + Command cmdProper = getProperCommand(); // set defaults first - initializeDefaults(store); + initializeDefaults(store, cmdProper); // get the properties now + final String postfix = " (" + Version.v1_4.getName() + ")"; String IdStr = store.getString(PreferenceEntry.preferenceListString.getString()); Command command = Command.valueOf(IdStr); + int position = menuDataList.size(); + // open String openCmd = store.getString(PreferenceEntry.preferenceTargetOpen.getString()); + CommandData cmdDataOpen = new CommandData(null, PresetType.presetUser, os, command.getConsole(), ResourceType.resourceTypeFileOrDirectory, false, null, Category.categoryOpen, CommandType.commandTypeExecute, migrateCommandVariables(openCmd)); + cmdDataList.add(cmdDataOpen); + MenuData menuDataOpen = new MenuData(cmdDataOpen.getId(), true, MenuNameType.menuNameTypeOpenHere, null, cmdDataOpen.getId()); + menuDataOpen.setPosition(position++); + menuDataOpen.setNamePattern(menuDataOpen.getNamePattern() + postfix); + menuDataOpen.setNameType(MenuNameType.menuNameTypeUser); + menuDataList.add(menuDataOpen); + // run String runCmd = store.getString(PreferenceEntry.preferenceTargetRun.getString()); + CommandData cmdDataRun = new CommandData(null, PresetType.presetUser, os, command.getConsole(), ResourceType.resourceTypeFileOrDirectory, false, null, Category.categoryRun, CommandType.commandTypeExecute, migrateCommandVariables(runCmd)); + cmdDataList.add(cmdDataRun); + MenuData menuDataRun = new MenuData(cmdDataRun.getId(), true, MenuNameType.menuNameTypeRunWith, null, cmdDataRun.getId()); + menuDataRun.setPosition(position++); + menuDataRun.setNamePattern(menuDataRun.getNamePattern() + postfix); + menuDataRun.setNameType(MenuNameType.menuNameTypeUser); + menuDataList.add(menuDataRun); + // explore String exploreCmd = store.getString(PreferenceEntry.preferenceTargetExplore.getString()); + CommandData cmdDataExplore = new CommandData(null, PresetType.presetUser, os, command.getExplorer(), ResourceType.resourceTypeFileOrDirectory, false, null, Category.categoryExplore, CommandType.commandTypeExecute, migrateCommandVariables(exploreCmd)); + cmdDataList.add(cmdDataExplore); + MenuData menuDataExplore = new MenuData(cmdDataExplore.getId(), true, MenuNameType.menuNameTypeShowIn, null, cmdDataExplore.getId()); + menuDataExplore.setPosition(position++); + menuDataExplore.setNamePattern(menuDataExplore.getNamePattern() + postfix); + menuDataExplore.setNameType(MenuNameType.menuNameTypeUser); + menuDataList.add(menuDataExplore); + // copy to clipboard String copyPathCmd = store.getString(PreferenceEntry.preferenceTargetCopyPath.getString()); + CommandData cmdDataCopyPath = new CommandData(null, PresetType.presetUser, os, "Full Path", ResourceType.resourceTypeFileOrDirectory, false, null, Category.categoryClipboard, CommandType.commandTypeClipboard, migrateCommandVariables(copyPathCmd)); + cmdDataList.add(cmdDataCopyPath); + MenuData menuDataCopyPath = new MenuData(cmdDataCopyPath.getId(), true, MenuNameType.menuNameTypeCopyToClipboard, null, cmdDataCopyPath.getId()); + menuDataCopyPath.setPosition(position++); + menuDataCopyPath.setNamePattern(menuDataCopyPath.getNamePattern() + postfix); + menuDataCopyPath.setNameType(MenuNameType.menuNameTypeUser); + menuDataList.add(menuDataCopyPath); + /* String QuotesStr = store.getString(PreferenceEntry.preferenceQuotes.getString()); Quotes quotes = Quotes.valueOf(QuotesStr); String DebugStr = store.getString(PreferenceEntry.preferenceDebug.getString()); Debug debug = Debug.valueOf(DebugStr); String TokenizerStr = store.getString(PreferenceEntry.preferenceTokenizer.getString()); Tokenizer tokenizer = Tokenizer.valueOf(TokenizerStr); + */ return true; } + public static String migrateCommandVariables(String cmdString) { + /* + {0} == ${easyshell:drive} + {1} == ${easyshell:container_loc} + {2} == ${easyshell:resource_loc} + {3} == ${easyshell:resource_name} + {4} == ${easyshell:project_name} + {5} == ${easyshell:line_separator} + */ + String migratedString = cmdString; + migratedString = migratedString.replace("{0}", "${easyshell:drive}"); + migratedString = migratedString.replace("{1}", "${easyshell:container_loc}"); + migratedString = migratedString.replace("{2}", "${easyshell:resource_loc}"); + migratedString = migratedString.replace("{3}", "${easyshell:resource_name}"); + migratedString = migratedString.replace("{4}", "${easyshell:project_name}"); + migratedString = migratedString.replace("{5}", "${easyshell:line_separator}"); + return migratedString; + } + private static Command getProperCommand() { Command cmd = Command.cmdUnknown; /* possible OS string: diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/PrefsV1_5.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/PrefsV1_5.java index af2d1e16..bd0b2ecf 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/PrefsV1_5.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/PrefsV1_5.java @@ -21,7 +21,16 @@ import org.eclipse.jface.preference.IPreferenceStore; import de.anbos.eclipse.easyshell.plugin.preferences.CommandData; +import de.anbos.eclipse.easyshell.plugin.preferences.CommandDataList; import de.anbos.eclipse.easyshell.plugin.preferences.MenuData; +import de.anbos.eclipse.easyshell.plugin.preferences.MenuDataList; +import de.anbos.eclipse.easyshell.plugin.types.Category; +import de.anbos.eclipse.easyshell.plugin.types.CommandType; +import de.anbos.eclipse.easyshell.plugin.types.MenuNameType; +import de.anbos.eclipse.easyshell.plugin.types.OS; +import de.anbos.eclipse.easyshell.plugin.types.PresetType; +import de.anbos.eclipse.easyshell.plugin.types.ResourceType; +import de.anbos.eclipse.easyshell.plugin.types.Version; public class PrefsV1_5 { @@ -204,9 +213,7 @@ public PrefsV1_5() { /** * Sets the default values of the preferences. */ - public static void initializeDefaults(IPreferenceStore store, int instId) { - // get proper command (detect) - Command cmd = getProperCommand(); + public static void initializeDefaults(IPreferenceStore store, Command cmd, int instId) { // set default commands store.setDefault(PreferenceEntry.preferenceTargetEnabled.getString(instId), false); store.setDefault(PreferenceEntry.preferenceTargetOpen.getString(instId), cmd.getOpenCmd()); @@ -226,11 +233,11 @@ public static List getPreferenceList() { List list = new ArrayList(); list.add(PreferenceEntry.preferenceTargetEnabled.getString()); //list.add(PreferenceEntry.preferenceListId.getString()); - list.add(PreferenceEntry.preferenceListString.getString()); - list.add(PreferenceEntry.preferenceTargetOpen.getString()); - list.add(PreferenceEntry.preferenceTargetRun.getString()); - list.add(PreferenceEntry.preferenceTargetExplore.getString()); - list.add(PreferenceEntry.preferenceTargetCopyPath.getString()); + //list.add(PreferenceEntry.preferenceListString.getString()); + //list.add(PreferenceEntry.preferenceTargetOpen.getString()); + //list.add(PreferenceEntry.preferenceTargetRun.getString()); + //list.add(PreferenceEntry.preferenceTargetExplore.getString()); + //list.add(PreferenceEntry.preferenceTargetCopyPath.getString()); //list.add(PreferenceEntry.preferenceQuotes.getString()); //list.add(PreferenceEntry.preferenceDebug.getString()); //list.add(PreferenceEntry.preferenceTokenizer.getString()); @@ -242,7 +249,7 @@ public static List getPreferenceList() { * * @return store loaded. */ - public static boolean loadStore(IPreferenceStore store, List cmdDataList, List menuDataList) { + public static boolean loadStore(IPreferenceStore store, OS os, CommandDataList cmdDataList, MenuDataList menuDataList) { /* DebugStr=debugYes DebugStr1=debugNo @@ -271,23 +278,79 @@ public static boolean loadStore(IPreferenceStore store, List cmdDat targetRunPreference1=cmd.exe /C start "${easyshell\:project_name}" /D ${easyshell\:container_loc} powershell.exe -command ./''${easyshell\:resource_name}'' targetRunPreference2=cmd.exe /C start "${easyshell\:project_name}" /D ${easyshell\:container_loc} "C\:\\Cygwin\\bin\\bash.exe" -c ./''${easyshell\:resource_name}'' */ + // get proper command (detect) + Command cmdProper = getProperCommand(); + // duplicate cache + List openCmdList = new ArrayList(); + List runCmdList = new ArrayList(); + List exploreCmdList = new ArrayList(); + List copyPathList = new ArrayList(); + // iterate over the instances for (int instanceId=0;instanceId<3;instanceId++) { // set defaults first - initializeDefaults(store, instanceId); + initializeDefaults(store, cmdProper, instanceId); // get the properties now if (store.getBoolean(PreferenceEntry.preferenceTargetEnabled.getString(instanceId))) { + final String postfix = " (" + Version.v1_5.getName() + ")"; String IdStr = store.getString(PreferenceEntry.preferenceListString.getString(instanceId)); Command command = Command.valueOf(IdStr); + int position = menuDataList.size(); + // open String openCmd = store.getString(PreferenceEntry.preferenceTargetOpen.getString(instanceId)); + if (!openCmdList.contains(openCmd)) { + openCmdList.add(openCmd); + CommandData cmdDataOpen = new CommandData(null, PresetType.presetUser, os, command.getConsole(), ResourceType.resourceTypeFileOrDirectory, false, null, Category.categoryOpen, CommandType.commandTypeExecute, PrefsV1_4.migrateCommandVariables(openCmd)); + cmdDataList.add(cmdDataOpen); + MenuData menuDataOpen = new MenuData(cmdDataOpen.getId(), true, MenuNameType.menuNameTypeOpenHere, null, cmdDataOpen.getId()); + menuDataOpen.setPosition(position++); + menuDataOpen.setNamePattern(menuDataOpen.getNamePattern() + postfix); + menuDataOpen.setNameType(MenuNameType.menuNameTypeUser); + menuDataList.add(menuDataOpen); + } + // run String runCmd = store.getString(PreferenceEntry.preferenceTargetRun.getString(instanceId)); + if (!runCmdList.contains(runCmd)) { + runCmdList.add(runCmd); + CommandData cmdDataRun = new CommandData(null, PresetType.presetUser, os, command.getConsole(), ResourceType.resourceTypeFileOrDirectory, false, null, Category.categoryRun, CommandType.commandTypeExecute, PrefsV1_4.migrateCommandVariables(runCmd)); + cmdDataList.add(cmdDataRun); + MenuData menuDataRun = new MenuData(cmdDataRun.getId(), true, MenuNameType.menuNameTypeRunWith, null, cmdDataRun.getId()); + menuDataRun.setPosition(position++); + menuDataRun.setNamePattern(menuDataRun.getNamePattern() + postfix); + menuDataRun.setNameType(MenuNameType.menuNameTypeUser); + menuDataList.add(menuDataRun); + } + // explore String exploreCmd = store.getString(PreferenceEntry.preferenceTargetExplore.getString(instanceId)); + if (!exploreCmdList.contains(exploreCmd)) { + exploreCmdList.add(exploreCmd); + CommandData cmdDataExplore = new CommandData(null, PresetType.presetUser, os, command.getExplorer(), ResourceType.resourceTypeFileOrDirectory, false, null, Category.categoryExplore, CommandType.commandTypeExecute, PrefsV1_4.migrateCommandVariables(exploreCmd)); + cmdDataList.add(cmdDataExplore); + MenuData menuDataExplore = new MenuData(cmdDataExplore.getId(), true, MenuNameType.menuNameTypeShowIn, null, cmdDataExplore.getId()); + menuDataExplore.setPosition(position++); + menuDataExplore.setNamePattern(menuDataExplore.getNamePattern() + postfix); + menuDataExplore.setNameType(MenuNameType.menuNameTypeUser); + menuDataList.add(menuDataExplore); + } + // copy to clipboard String copyPathCmd = store.getString(PreferenceEntry.preferenceTargetCopyPath.getString(instanceId)); + if (!copyPathList.contains(copyPathCmd)) { + copyPathList.add(copyPathCmd); + CommandData cmdDataCopyPath = new CommandData(null, PresetType.presetUser, os, "Full Path", ResourceType.resourceTypeFileOrDirectory, false, null, Category.categoryClipboard, CommandType.commandTypeClipboard, PrefsV1_4.migrateCommandVariables(copyPathCmd)); + cmdDataList.add(cmdDataCopyPath); + MenuData menuDataCopyPath = new MenuData(cmdDataCopyPath.getId(), true, MenuNameType.menuNameTypeCopyToClipboard, null, cmdDataCopyPath.getId()); + menuDataCopyPath.setPosition(position++); + menuDataCopyPath.setNamePattern(menuDataCopyPath.getNamePattern() + postfix); + menuDataCopyPath.setNameType(MenuNameType.menuNameTypeUser); + menuDataList.add(menuDataCopyPath); + } + /* String QuotesStr = store.getString(PreferenceEntry.preferenceQuotes.getString(instanceId)); Quotes quotes = Quotes.valueOf(QuotesStr); String DebugStr = store.getString(PreferenceEntry.preferenceDebug.getString(instanceId)); Debug debug = Debug.valueOf(DebugStr); String TokenizerStr = store.getString(PreferenceEntry.preferenceTokenizer.getString(instanceId)); Tokenizer tokenizer = Tokenizer.valueOf(TokenizerStr); + */ } } return true; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java index e5a9c20d..d06174a7 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java @@ -39,19 +39,19 @@ public class CommandData extends Data { public CommandData(String id, PresetType presetType, OS os, String name, ResourceType resType, boolean useWorkingDirectory, String workingDirectory, Category category, CommandType cmdType, String command) { super(id); - this.presetType = presetType; - this.os = os; - this.name = name; - this.resourceType = resType; - this.useWorkingDirectory = useWorkingDirectory; - this.workingDirectory = workingDirectory; - this.category = category; - this.commandType = cmdType; - this.command = command; + setPresetType(presetType); + setOs(os); + setName(name); + setResourceType(resType); + setUseWorkingDirectory(useWorkingDirectory); + setWorkingDirectory(workingDirectory); + setCategory(category); + setCommandType(cmdType); + setCommand(command); } public CommandData(String id, PresetType presetType, OS os, String name, ResourceType resType, Category category, CommandType cmdType, String command) { - this(id, presetType, os, name, resType, false, "${easyshell:container_loc}", category, cmdType, command); + this(id, presetType, os, name, resType, false, null, category, cmdType, command); } public CommandData(CommandData commandData, String newId) { @@ -129,7 +129,11 @@ public void setUseWorkingDirectory(boolean useWorkingDirectory) { } public void setWorkingDirectory(String workingDirectory) { - this.workingDirectory = workingDirectory; + if (workingDirectory != null) { + this.workingDirectory = workingDirectory; + } else { + this.workingDirectory = "${easyshell:container_loc}"; + } } public void setCategory(Category category) { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java index f0f1c83c..d7d3f8be 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java @@ -11,9 +11,7 @@ package de.anbos.eclipse.easyshell.plugin.preferences; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; import de.anbos.eclipse.easyshell.plugin.Activator; @@ -28,22 +26,16 @@ public class CommandDataDefaultCollection { - private List list = new ArrayList(); + private CommandDataList list = new CommandDataList(); private static CommandDataDefaultCollection instance = new CommandDataDefaultCollection(); - public static List getAllCommandsStatic(boolean sorted) { - List ret = instance.getCommands(); - if (sorted) { - for (int i=0;i getCommandsNativeAsMenu(boolean sorted) { - List list = getDefaultCommands(); - List ret = new ArrayList(); + public static MenuDataList getCommandsNativeAsMenu(boolean sorted) { + CommandDataList list = getDefaultCommands(); + MenuDataList ret = new MenuDataList(); for (int i=0;i getCommands() { + public CommandDataList getCommands() { return list; } - public static List getCommandsNative(List list, boolean sorted) { + public static CommandDataList getCommandsNative(CommandDataList list) { if (list == null) { - list = getAllCommandsStatic(false); + list = getAllCommandsStatic(); } - return getCommandData(list, Utils.getOS(), sorted); + return getCommandData(list, Utils.getOS()); } - private static List getDefaultCommands() { - List listAll = getAllCommandsStatic(false); - List listOS = new ArrayList(); - List listDefault = new ArrayList(); + private static CommandDataList getDefaultCommands() { + CommandDataList listAll = getAllCommandsStatic(); + CommandDataList listOS = new CommandDataList(); + CommandDataList listDefault = new CommandDataList(); OS os = Utils.getOS(); // now get all data by OS - listOS = getCommandData(listAll, os, true); + listOS = getCommandData(listAll, os); // now get by name switch(os) { @@ -276,29 +268,24 @@ private static List getDefaultCommands() { return listDefault; } - private static void addNotNull(List list, CommandData data) { + private static void addNotNull(CommandDataList list, CommandData data) { if (data != null) { list.add(data); } } - public static List getCommandData(List list, OS os, boolean sorted) { - List listOut = new ArrayList(); - int position = 0; + public static CommandDataList getCommandData(CommandDataList list, OS os) { + CommandDataList listOut = new CommandDataList(); for (CommandData entry : list) { if (entry.getOs() == os) { CommandData newData = new CommandData(entry, false); - if (sorted) { - newData.setPosition(position); - } listOut.add(newData); - position++; } } return listOut; } - private static CommandData getCommandData(List list, String name, Category category) { + private static CommandData getCommandData(CommandDataList list, String name, Category category) { for (CommandData entry : list) { if (entry.getCategory() == category && entry.getName().matches(name)) { return entry; @@ -307,8 +294,8 @@ private static CommandData getCommandData(List list, String name, C return null; } - private static List getCommandDataList(List list, Category category) { - List listOut = new ArrayList(); + private static CommandDataList getCommandDataList(CommandDataList list, Category category) { + CommandDataList listOut = new CommandDataList(); for (CommandData entry : list) { if (entry.getCategory() == category) { CommandData newData = new CommandData(entry, false); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataList.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataList.java new file mode 100644 index 00000000..560db9a9 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataList.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +import java.util.ArrayList; +import java.util.List; + +public class CommandDataList extends ArrayList { + + /** + * + */ + private static final long serialVersionUID = 6519662599078432983L; + + public CommandDataList() { + } + + public CommandDataList(List list) { + addAll(list); + } + + @Override + public boolean add(CommandData e) { + e.setPosition(this.size()); + return super.add(e); + } + +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataStore.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataStore.java index 0de77565..4049a55d 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataStore.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataStore.java @@ -11,9 +11,6 @@ package de.anbos.eclipse.easyshell.plugin.preferences; -import java.util.ArrayList; -import java.util.List; - import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; @@ -45,8 +42,8 @@ public void propertyChange(PropertyChangeEvent event) { }); } - private List getUserCommands() { - List userItems = new ArrayList(); + private CommandDataList getUserCommands() { + CommandDataList userItems = new CommandDataList(); for (CommandData data : getDataList()) { if (data.getPresetType() == PresetType.presetUser) { userItems.add(data); @@ -55,8 +52,8 @@ private List getUserCommands() { return userItems; } - private List getPresetCommands() { - List presetItems = new ArrayList(); + private CommandDataList getPresetCommands() { + CommandDataList presetItems = new CommandDataList(); for (CommandData data : getDataList()) { if (data.getPresetType() == PresetType.presetPlugin) { presetItems.add(data); @@ -66,7 +63,7 @@ private List getPresetCommands() { } public CommandData[] getAllCommandsArray() { - List allItems = getDataList(); + CommandDataList allItems = new CommandDataList(getDataList()); if(allItems.size() <= 0) { return new CommandData[0]; } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java index ca2e046e..753b5429 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java @@ -102,7 +102,7 @@ protected void performApply() { @Override protected void performDefaults() { // get the selected commands and referenced menus as lists - List commands = CommandDataStore.instance().getDataList(); + CommandDataList commands = new CommandDataList(CommandDataStore.instance().getDataList()); List menus = new ArrayList(); for(CommandData command : commands) { if (command.getPresetType() == PresetType.presetUser) { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Data.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Data.java index f8366d66..387d18a4 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Data.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Data.java @@ -27,18 +27,21 @@ public Data(String id) { } } - public Data(String newId, IData data) { - this(newId); + public Data(String id, int position) { + this(id); + setPosition(position); } public Data(IData data, boolean generateNewId) { - this(generateNewId ? UUID.randomUUID().toString() : data.getId(), data); + this(generateNewId ? null : data.getId()); } public Data(IData data) { + this(data.getId()); } public Data() { + this(null, true); } /* (non-Javadoc) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/DataStore.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/DataStore.java index 3f952fda..ee9f6e6e 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/DataStore.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/DataStore.java @@ -172,6 +172,7 @@ protected IPreferenceStore getStore() { } protected void addItem(T data) { + data.setPosition(items.size()); items.add(data); } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java index 1df4560c..790cc0ff 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/Initializer.java @@ -39,7 +39,7 @@ public void initializeDefaultPreferences() { } private void setDefaults(IPreferenceStore store) { - String defaultCommandsPreset = PreferenceValueConverter.asCommandDataString(CommandDataDefaultCollection.getCommandsNative(null, true)); + String defaultCommandsPreset = PreferenceValueConverter.asCommandDataString(CommandDataDefaultCollection.getCommandsNative(null)); String defaultCommands = ""; String defaultMenu = PreferenceValueConverter.asMenuDataString(CommandDataDefaultCollection.getCommandsNativeAsMenu(true)); store.setDefault(Constants.PREF_COMMANDS_PRESET, defaultCommandsPreset); @@ -144,9 +144,9 @@ private int migrate_from_v1(IPreferenceStore store, Version version, int migrate // check preferences for default values migrateState = migrate_check_pref_and_ask_user(oldStore, version, PrefsV1_5.getPreferenceList(), migrateState); if (migrateState == 0) { - List cmdDataList = new ArrayList(); - List menuDataList = new ArrayList(); - if (PrefsV1_5.loadStore(oldStore, cmdDataList, menuDataList)) { + CommandDataList cmdDataList = new CommandDataList(); + MenuDataList menuDataList = CommandDataDefaultCollection.getCommandsNativeAsMenu(true); + if (PrefsV1_5.loadStore(oldStore, Utils.getOS(), cmdDataList, menuDataList)) { store.setValue(Constants.PREF_COMMANDS, PreferenceValueConverter.asCommandDataString(cmdDataList)); store.setValue(Constants.PREF_MENU, PreferenceValueConverter.asMenuDataString(menuDataList)); } @@ -154,9 +154,9 @@ private int migrate_from_v1(IPreferenceStore store, Version version, int migrate } else if (version == Version.v1_4) { // check preferences for default values migrateState = migrate_check_pref_and_ask_user(oldStore, version, PrefsV1_4.getPreferenceList(), migrateState); - List cmdDataList = new ArrayList(); - List menuDataList = new ArrayList(); - if (PrefsV1_4.loadStore(oldStore, cmdDataList, menuDataList)) { + CommandDataList cmdDataList = new CommandDataList(); + MenuDataList menuDataList = CommandDataDefaultCollection.getCommandsNativeAsMenu(true); + if (PrefsV1_4.loadStore(oldStore, Utils.getOS(), cmdDataList, menuDataList)) { store.setValue(Constants.PREF_COMMANDS, PreferenceValueConverter.asCommandDataString(cmdDataList)); store.setValue(Constants.PREF_MENU, PreferenceValueConverter.asMenuDataString(menuDataList)); } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java index 0219a9e5..0c8d1718 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java @@ -27,12 +27,12 @@ public class MenuData extends Data { // copy of or reference to command private String commandId = null; - public MenuData(String id, boolean enabled, MenuNameType nameType, String namePattern, String commandId) { + public MenuData(String id, boolean enabled, MenuNameType nameType, String namePattern,String commandId) { super(id); - this.enabled = enabled; - this.nameType = nameType; - this.namePattern = namePattern; - this.commandId = commandId; + setEnabled(enabled); + setNameType(nameType); + setNamePattern(namePattern); + setCommandId(commandId); } public MenuData(String newId, String commandId) { @@ -192,7 +192,9 @@ public void setNameType(MenuNameType nameType) { } public void setNamePattern(String namePattern) { - this.namePattern = namePattern; + if (namePattern != null) { + this.namePattern = namePattern; + } } public void setCommandId(String commandId) { @@ -223,7 +225,7 @@ public void setNameTypeFromCategory(Category category) { case categoryClipboard: setNameType(MenuNameType.menuNameTypeCopyToClipboard); break; } - + } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataList.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataList.java new file mode 100644 index 00000000..bd5790e8 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataList.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +import java.util.ArrayList; +import java.util.List; + +public class MenuDataList extends ArrayList { + + /** + * + */ + private static final long serialVersionUID = 4274345194237037872L; + + public MenuDataList() { + } + + public MenuDataList(List list) { + addAll(list); + } + + @Override + public boolean add(MenuData e) { + e.setPosition(this.size()); + return super.add(e); + } + +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java index 85ee6967..1ddc7d29 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java @@ -11,9 +11,7 @@ package de.anbos.eclipse.easyshell.plugin.preferences; -import java.util.ArrayList; import java.util.Iterator; -import java.util.List; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.util.IPropertyChangeListener; @@ -46,7 +44,7 @@ public void propertyChange(PropertyChangeEvent event) { } public MenuData[] getCommandMenuDataArray() { - List allItems = getDataList(); + MenuDataList allItems = new MenuDataList(getDataList()); if(allItems.size() <= 0) { return new MenuData[0]; } @@ -57,8 +55,8 @@ public MenuData[] getCommandMenuDataArray() { return allArray; } - public List getEnabledCommandMenuDataList() { - List checkedItems = new ArrayList(); + public MenuDataList getEnabledCommandMenuDataList() { + MenuDataList checkedItems = new MenuDataList(); Iterator dataIterator = getDataList().iterator(); while(dataIterator.hasNext()) { MenuData data = (MenuData)dataIterator.next(); @@ -70,7 +68,7 @@ public List getEnabledCommandMenuDataList() { } public MenuData[] getEnabledCommandMenuDataArray() { - List checkedItems = getEnabledCommandMenuDataList(); + MenuDataList checkedItems = getEnabledCommandMenuDataList(); if(checkedItems.size() <= 0) { return new MenuData[0]; } @@ -109,8 +107,8 @@ public void load() { load(null); } - public List getRefencedBy(String id) { - List ref = new ArrayList(); + public MenuDataList getRefencedBy(String id) { + MenuDataList ref = new MenuDataList(); Iterator dataIterator = getDataList().iterator(); while(dataIterator.hasNext()) { MenuData data = (MenuData)dataIterator.next(); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java index 934a56b8..4970d378 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java @@ -131,7 +131,7 @@ protected Control createContents(Composite parent) { CommandDataStore.instance().load(); // get the native commands list - commandList = CommandDataDefaultCollection.getCommandsNative(CommandDataStore.instance().getDataList(), true); + commandList = CommandDataDefaultCollection.getCommandsNative(new CommandDataList(CommandDataStore.instance().getDataList())); // menu store MenuDataStore.instance().load(); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/MenuNameType.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/MenuNameType.java index e749e769..8239d4b6 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/MenuNameType.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/MenuNameType.java @@ -19,11 +19,12 @@ public enum MenuNameType { menuNameTypeUser( 0, "User defined", "${easyshell:command_name}"), menuNameTypeDefaultApplication( 1, "Open with default application", "Open with default Application"), menuNameTypeOpenHere( 2, "Open Here", "Open ${easyshell:command_name} Here"), - menuNameTypeShowIn( 3, "Show in ", "Show in ${easyshell:command_name}"), - menuNameTypeCopyToClipboard( 4, "Copy to Clipboard", "Copy ${easyshell:command_name} to Clipboard"), - menuNameTypeGeneric1( 5, ": ", "${easyshell:command_category}: ${easyshell:command_name}"), - menuNameTypeGeneric2( 6, " with ", "${easyshell:command_category} with ${easyshell:command_name}"), - menuNameTypeGeneric3( 7, " with ", "${easyshell:command_category} with ${easyshell:command_os} ${easyshell:command_name}"); + menuNameTypeRunWith( 3, "Run with ", "Run with ${easyshell:command_name}"), + menuNameTypeShowIn( 4, "Show in ", "Show in ${easyshell:command_name}"), + menuNameTypeCopyToClipboard( 5, "Copy to Clipboard", "Copy ${easyshell:command_name} to Clipboard"), + menuNameTypeGeneric1( 6, ": ", "${easyshell:command_category}: ${easyshell:command_name}"), + menuNameTypeGeneric2( 7, " with ", "${easyshell:command_category} with ${easyshell:command_name}"), + menuNameTypeGeneric3( 9, " with ", "${easyshell:command_category} with ${easyshell:command_os} ${easyshell:command_name}"); // attributes private final int id; private final String name; From 7a45329808c1bb4343a2be2b78a74bd5a4b60fb2 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Mon, 5 Sep 2016 19:25:57 +0200 Subject: [PATCH 47/73] #81 [v2.0] "Copy Full Path to Clipboard" missing at Mac OS X - moved Windows preset with quotes \"Full Path\" to all OS presets - added \"Qualified Name\" to all OS presets (reused UUID: was MAC OS X clipboard before) Signed-off-by: Andre Bossert --- .../preferences/CommandDataDefaultCollection.java | 13 ++++++++----- uuids.txt | 15 ++++++++------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java index d7d3f8be..f9475948 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java @@ -100,9 +100,6 @@ private void addWindowsCommands() { // Windows TotalCommander list.add(new CommandData("e487327c-dfdb-42e7-bf16-3b81a34e5703", PresetType.presetPlugin, OS.osWindows, "TotalCommander", ResourceType.resourceTypeFileOrDirectory, Category.categoryExplore, CommandType.commandTypeExecute, "cmd.exe /C totalcmd64.exe /O /T ${easyshell:container_loc}")); - // Windows Clipboard - Full Path - list.add(new CommandData("67aa9dff-6bbb-4b47-8b43-8a82a7a279fa", PresetType.presetPlugin, OS.osWindows, "Full Path", ResourceType.resourceTypeFileOrDirectory, Category.categoryClipboard, CommandType.commandTypeClipboard, - "\"${easyshell:resource_loc}\"${easyshell:line_separator}")); } private void addLinuxCommands() { @@ -175,11 +172,17 @@ private void addMacOSXCommands() { private void addAllOSCommands() { // Clipboard - Full Path - list.add(new CommandData("33043fe3-1a5f-46d7-b94e-9a02ef204e7d", PresetType.presetPlugin, OS.osLinux, "Full Path", ResourceType.resourceTypeFileOrDirectory, Category.categoryClipboard, CommandType.commandTypeClipboard, + list.add(new CommandData("33043fe3-1a5f-46d7-b94e-9a02ef204e7d", PresetType.presetPlugin, Utils.getOS(), "Full Path", ResourceType.resourceTypeFileOrDirectory, Category.categoryClipboard, CommandType.commandTypeClipboard, "${easyshell:resource_loc}${easyshell:line_separator}")); - // Clipboard - Qualified name + // Clipboard - Full Path with quotes + list.add(new CommandData("67aa9dff-6bbb-4b47-8b43-8a82a7a279fa", PresetType.presetPlugin, Utils.getOS(), "\"Full Path\"", ResourceType.resourceTypeFileOrDirectory, Category.categoryClipboard, CommandType.commandTypeClipboard, + "\"${easyshell:resource_loc}\"${easyshell:line_separator}")); + // Clipboard - Qualified Name list.add(new CommandData("88989d78-cf17-4750-91fc-6260055743ae", PresetType.presetPlugin, Utils.getOS(), "Qualified Name", ResourceType.resourceTypeFileOrDirectory, Category.categoryClipboard, CommandType.commandTypeClipboard, "${easyshell:qualified_name}${easyshell:line_separator}")); + // Clipboard - Qualified Name with quotes + list.add(new CommandData("cd32fa5a-34d7-4551-8bd0-3aae0dc444d0", PresetType.presetPlugin, Utils.getOS(), "\"Qualified Name\"", ResourceType.resourceTypeFileOrDirectory, Category.categoryClipboard, CommandType.commandTypeClipboard, + "\"${easyshell:qualified_name}\"${easyshell:line_separator}")); // Clipboard - Variables Test String varTestString = ""; for(int i=1;i Date: Mon, 5 Sep 2016 19:48:01 +0200 Subject: [PATCH 48/73] #82 [v2.0] ${easyshell:resource_loc} missing in "usable variables" Signed-off-by: Andre Bossert --- .../eclipse/easyshell/plugin/preferences/CommandDataDialog.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java index 9dc7513d..685b63c3 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java @@ -129,7 +129,7 @@ public Control createDialogArea(Composite parent) { pageGroup2.setFont(parent.getFont()); // create variable labels - for(int i=1;i Date: Mon, 12 Sep 2016 18:53:07 +0200 Subject: [PATCH 49/73] #83 [v2.0] rework "Copy..." and "Show/Edit.." buttons in command dialog Signed-off-by: Andre Bossert --- .../easyshell/plugin/UIMessages.properties | 19 +- .../plugin/preferences/CommandData.java | 172 +++++++++++++----- .../plugin/preferences/CommandDataBasic.java | 140 ++++++++++++++ .../plugin/preferences/CommandDataDialog.java | 58 +++--- .../plugin/preferences/CommandDataStore.java | 2 +- .../plugin/preferences/CommandPage.java | 79 +++++--- .../plugin/preferences/MenuDataDialog.java | 81 +++++---- .../plugin/preferences/MenuPage.java | 2 +- .../easyshell/plugin/types/PresetType.java | 3 +- 9 files changed, 419 insertions(+), 137 deletions(-) create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataBasic.java diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties index 05c7497b..14d26f9f 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties @@ -46,14 +46,18 @@ easyshell.command.page.button.text.new=Add... easyshell.command.page.button.tooltip.new=Add new command easyshell.command.page.button.text.copy=Copy... easyshell.command.page.button.tooltip.copy=Copy selected command to new command -easyshell.command.page.button.text.edit=Show/Edit... +easyshell.command.page.button.text.edit=Edit... easyshell.command.page.button.tooltip.edit=Show or edit selected command easyshell.command.page.button.text.remove=Remove... -easyshell.command.page.button.tooltip.remove=Remove selected commands(s) +easyshell.command.page.button.tooltip.remove=Remove selected command(s) or user settings easyshell.command.page.dialog.remove.title=Remove command(s) +easyshell.command.page.dialog.remove.user.title=Remove user settings easyshell.command.page.dialog.remove.question=Do you really want to remove selected command(s):\n\n{0} +easyshell.command.page.dialog.remove.user.question=Do you really want to remove user settings from selected command(s):\n\n{0} easyshell.command.page.dialog.remove.menu.title=Remove command(s) and menu(s) +easyshell.command.page.dialog.remove.menu.user.title=Remove user settings easyshell.command.page.dialog.remove.menu.question=The selected command(s):\n\n{0}\nis(are) used in menu(s):\n\n{1}\nDo you really want to remove selected command(s) and menu(s) ? +easyshell.command.page.dialog.remove.menu.user.question=The selected command(s):\n\n{0}\nis(are) used in menu(s):\n\n{1}\nDo you really want to remove user settings from selected command(s) ? easyshell.command.page.dialog.defaults.title=Restore defaults easyshell.command.page.dialog.defaults.question=All your command definitions will be overwritten!\n\nYou can still use "Cancel" button afterwards for undo.\n\nDo you really want to restore default settings? @@ -78,21 +82,24 @@ easyshell.menu.editor.dialog.button.text.new=New... easyshell.menu.editor.dialog.button.tooltip.new=Add new command easyshell.menu.editor.dialog.button.text.copy=Copy... easyshell.menu.editor.dialog.button.tooltip.copy=Copy selected command to new command -easyshell.menu.editor.dialog.button.text.edit=Show/Edit... +easyshell.menu.editor.dialog.button.text.edit=Edit... easyshell.menu.editor.dialog.button.tooltip.edit=Show or edit selected command easyshell.menu.editor.dialog.button.text.remove=Remove... -easyshell.menu.editor.dialog.button.tooltip.remove=Remove selected command +easyshell.menu.editor.dialog.button.tooltip.remove=Remove selected command or user settings easyshell.menu.editor.dialog.title.remove=Remove command +easyshell.menu.editor.dialog.title.user.remove=Remove user settings easyshell.menu.editor.dialog.question.remove=Do you really want to remove command\n"{0}" ? +easyshell.menu.editor.dialog.question.user.remove=Do you really want to remove user settings from command\n"{0}" ? easyshell.menu.editor.dialog.title.remove.menu=Remove command and menu(s) +easyshell.menu.editor.dialog.title.remove.user.menu=Remove user settings easyshell.menu.editor.dialog.question.remove.menu=The selected command:\n\n{0}\n\nis used in other menu(s):\n\n{1}\nDo you really want to remove selected command and menu(s) ? +easyshell.menu.editor.dialog.question.remove.user.menu=The selected command:\n\n{0}\n\nis used in other menu(s):\n\n{1}\nDo you really want to remove user settings from selected command? easyshell.menu.editor.dialog.title.duplicate=Duplicate usage of command easyshell.menu.editor.dialog.question.duplicate=The selected command:\n\n{0}\n\nis used in other menu(s) already:\n\n{1}\nDo you really want to use the same command in this menu ? easyshell.command.editor.dialog.title.new=Create new command easyshell.command.editor.dialog.title.copy=Copy to new command -easyshell.command.editor.dialog.title.edit=Edit command (defined by user) -easyshell.command.editor.dialog.title.show=Show command (defined by plugin) +easyshell.command.editor.dialog.title.edit=Edit command defined by {0} easyshell.command.editor.dialog.title.group1=Command easyshell.command.editor.dialog.tooltip.group1=Add your command here easyshell.command.editor.dialog.title.group2=Usable variables diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java index d06174a7..fa8a9efe 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java @@ -27,27 +27,25 @@ public class CommandData extends Data { // command + private CommandDataBasic basicData = null; private PresetType presetType = PresetType.presetUnknown; private OS os = OS.osUnknown; - private String name = ""; - private ResourceType resourceType = ResourceType.resourceTypeUnknown; - private boolean useWorkingDirectory = false; - private String workingDirectory = ""; private Category category = Category.categoryUnknown; private CommandType commandType = CommandType.commandTypeUnknown; - private String command = ""; + private CommandDataBasic userData = null; - public CommandData(String id, PresetType presetType, OS os, String name, ResourceType resType, boolean useWorkingDirectory, String workingDirectory, Category category, CommandType cmdType, String command) { + public CommandData(String id, CommandDataBasic basicData, PresetType presetType, OS os, Category category, CommandType cmdType, CommandDataBasic userData) { super(id); + setBasicData(basicData); setPresetType(presetType); setOs(os); - setName(name); - setResourceType(resType); - setUseWorkingDirectory(useWorkingDirectory); - setWorkingDirectory(workingDirectory); setCategory(category); setCommandType(cmdType); - setCommand(command); + setUserData(userData); + } + + public CommandData(String id, PresetType presetType, OS os, String name, ResourceType resType, boolean useWorkingDirectory, String workingDirectory, Category category, CommandType cmdType, String command) { + this(id, new CommandDataBasic(name, resType, useWorkingDirectory, workingDirectory, command), presetType, os, category, cmdType, null); } public CommandData(String id, PresetType presetType, OS os, String name, ResourceType resType, Category category, CommandType cmdType, String command) { @@ -55,7 +53,7 @@ public CommandData(String id, PresetType presetType, OS os, String name, Resourc } public CommandData(CommandData commandData, String newId) { - this(newId, commandData.getPresetType(), commandData.getOs(), commandData.getName(), commandData.getResourceType(), commandData.isUseWorkingDirectory(), commandData.getWorkingDirectory(), commandData.getCategory(), commandData.getCommandType(), commandData.getCommand()); + this(newId, commandData.getBasicData(), commandData.getPresetType(), commandData.getOs(), commandData.getCategory(), commandData.getCommandType(), commandData.getUserData()); } public CommandData(CommandData commandData, boolean generateNewId) { @@ -63,10 +61,23 @@ public CommandData(CommandData commandData, boolean generateNewId) { } public CommandData() { + basicData = new CommandDataBasic(); + } + + public CommandDataBasic getBasicData() { + return basicData; + } + + public CommandDataBasic getUserData() { + return userData; } public String getName() { - return name; + if (getPresetType() == PresetType.presetPluginAndUser) { + return userData.getName(); + } else { + return basicData.getName(); + } } public OS getOs() { @@ -78,15 +89,27 @@ public PresetType getPresetType() { } public ResourceType getResourceType() { - return resourceType; + if (getPresetType() == PresetType.presetPluginAndUser) { + return userData.getResourceType(); + } else { + return basicData.getResourceType(); + } } public boolean isUseWorkingDirectory() { - return useWorkingDirectory; + if (getPresetType() == PresetType.presetPluginAndUser) { + return userData.isUseWorkingDirectory(); + } else { + return basicData.isUseWorkingDirectory(); + } } public String getWorkingDirectory() { - return workingDirectory; + if (getPresetType() == PresetType.presetPluginAndUser) { + return userData.getWorkingDirectory(); + } else { + return basicData.getWorkingDirectory(); + } } public Category getCategory() { @@ -98,18 +121,56 @@ public CommandType getCommandType() { } public String getCommand() { - return command; + if (getPresetType() == PresetType.presetPluginAndUser) { + return userData.getCommand(); + } else { + return basicData.getCommand(); + } } public Image getCategoryImage() { return new Image(null, Activator.getImageDescriptor(getCategory().getIcon()).getImageData()); } + public String getCommandAsComboName() { return getCategory().getName() + " - " + getName() + " (" + getPresetType().getName() + ")" /*+ getOs().getName() + " - "*/; } + public boolean checkIfUserDataOverridesPreset(CommandDataBasic userData) { + if (getPresetType() == PresetType.presetPlugin) { + return !basicData.equals(userData); + } + return false; + } + + public void setBasicData(CommandDataBasic basicData) { + this.basicData = basicData; + } + + public void setUserData(CommandDataBasic userData) { + this.userData = userData; + } + + public void addUserData(CommandDataBasic userData) { + if (getPresetType() != PresetType.presetPluginAndUser) { + setPresetType(PresetType.presetPluginAndUser); + } + setUserData(userData); + } + + public void removeUserData() { + if (getPresetType() == PresetType.presetPluginAndUser) { + setPresetType(PresetType.presetPlugin); + } + setUserData(null); + } + public void setName(String name) { - this.name = name; + if (getPresetType() == PresetType.presetPluginAndUser) { + userData.setName(name); + } else { + basicData.setName(name); + } } public void setOs(OS os) { @@ -121,18 +182,26 @@ public void setPresetType(PresetType presetType) { } public void setResourceType(ResourceType resType) { - this.resourceType = resType; + if (getPresetType() == PresetType.presetPluginAndUser) { + userData.setResourceType(resType); + } else { + basicData.setResourceType(resType); + } } public void setUseWorkingDirectory(boolean useWorkingDirectory) { - this.useWorkingDirectory = useWorkingDirectory; + if (getPresetType() == PresetType.presetPluginAndUser) { + userData.setUseWorkingDirectory(useWorkingDirectory); + } else { + basicData.setUseWorkingDirectory(useWorkingDirectory); + } } public void setWorkingDirectory(String workingDirectory) { - if (workingDirectory != null) { - this.workingDirectory = workingDirectory; + if (getPresetType() == PresetType.presetPluginAndUser) { + userData.setWorkingDirectory(workingDirectory); } else { - this.workingDirectory = "${easyshell:container_loc}"; + basicData.setWorkingDirectory(workingDirectory); } } @@ -145,7 +214,11 @@ public void setCommandType(CommandType cmdType) { } public void setCommand(String command) { - this.command = command; + if (getPresetType() == PresetType.presetPluginAndUser) { + userData.setCommand(command); + } else { + basicData.setCommand(command); + } } public boolean equals(Object object) { @@ -154,13 +227,12 @@ public boolean equals(Object object) { } CommandData data = (CommandData)object; if(data.getId().equals(this.getId()) - /*data.getPosition() == this.getPosition() &&*/ - /*data.getName().equals(this.getName()) && - data.getOS() == this.getOS() && - data.getPresetType() == this.getPresetType() && - data.getResourceType() == this.getResourceType() && - data.getCommandType() == this.getCommandType() && - data.getCommand().equals(this.getCommand()*/ + /*data.getPosition() == this.getPosition() && + data.getBasicData().equals(this.getBasicData()) && + data.getPresetType() == this.getPresetType() && + data.getOS() == this.getOS() && + data.getCategory() == this.getCategory() && + data.getCommandType() == this.getCommandType() &&*/ ) { return true; @@ -179,25 +251,32 @@ public boolean deserialize(Version version, String value, StringTokenizer tokeni setPosition(Integer.parseInt(tokenizer.nextToken())); setId(tokenizer.nextToken()); // set command data members - setPresetType(PresetType.getFromEnum(tokenizer.nextToken())); + presetType = PresetType.getFromEnum(tokenizer.nextToken()); setOs(OS.getFromEnum(tokenizer.nextToken())); - setName(tokenizer.nextToken()); - setResourceType(ResourceType.getFromEnum(tokenizer.nextToken())); + basicData.setName(tokenizer.nextToken()); + basicData.setResourceType(ResourceType.getFromEnum(tokenizer.nextToken())); // handling of working directory if (version.getId() >= Version.v2_0_003.getId()) { - setUseWorkingDirectory(Boolean.valueOf(tokenizer.nextToken()).booleanValue()); - setWorkingDirectory(tokenizer.nextToken()); + basicData.setUseWorkingDirectory(Boolean.valueOf(tokenizer.nextToken()).booleanValue()); + basicData.setWorkingDirectory(tokenizer.nextToken()); setCategory(Category.getFromEnum(tokenizer.nextToken())); setCommandType(CommandType.getFromEnum(tokenizer.nextToken())); } else { - setUseWorkingDirectory(false); - setWorkingDirectory("${easyshell:container_loc}"); + basicData.setUseWorkingDirectory(false); + basicData.setWorkingDirectory("${easyshell:container_loc}"); String commandTypeStr = tokenizer.nextToken(); setCategory(Category.getFromDeprecatedCommandTypeEnum(commandTypeStr)); setCommandType(CommandType.getFromDeprecatedCommandTypeEnum(commandTypeStr)); } // go on compatible - setCommand(tokenizer.nextToken()); + basicData.setCommand(tokenizer.nextToken()); + if (version.getId() >= Version.v2_0_005.getId()) { + // let read userData if there + if (getPresetType() == PresetType.presetPluginAndUser) { + setUserData(new CommandDataBasic()); + userData.deserialize(version, null, tokenizer, delimiter); + } + } return true; } @@ -210,15 +289,20 @@ public String serialize(Version version, String delimiter) { ret += getId() + delimiter; ret += getPresetType().toString() + delimiter; ret += getOs().toString() + delimiter; - ret += getName() + delimiter; - ret += getResourceType().toString() + delimiter; + ret += basicData.getName() + delimiter; + ret += basicData.getResourceType().toString() + delimiter; if (version.getId() >= Version.v2_0_003.getId()) { - ret += Boolean.toString(isUseWorkingDirectory()) + delimiter; - ret += getWorkingDirectory() + delimiter; + ret += Boolean.toString(basicData.isUseWorkingDirectory()) + delimiter; + ret += basicData.getWorkingDirectory() + delimiter; ret += getCategory().toString() + delimiter; } ret += getCommandType().toString() + delimiter; - ret += getCommand() + delimiter; + ret += basicData.getCommand() + delimiter; + if (version.getId() >= Version.v2_0_005.getId()) { + if (getPresetType() == PresetType.presetPluginAndUser) { + ret += userData.serialize(version, delimiter); + } + } return ret; } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataBasic.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataBasic.java new file mode 100644 index 00000000..810639a3 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataBasic.java @@ -0,0 +1,140 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.preferences; + +import java.util.StringTokenizer; + +import de.anbos.eclipse.easyshell.plugin.types.ResourceType; +import de.anbos.eclipse.easyshell.plugin.types.Version; + +public class CommandDataBasic { + + // command + private String name = ""; + private ResourceType resourceType = ResourceType.resourceTypeUnknown; + private boolean useWorkingDirectory = false; + private String workingDirectory = ""; + private String command = ""; + + public CommandDataBasic(String name, ResourceType resType, boolean useWorkingDirectory, String workingDirectory, String command) { + setName(name); + setResourceType(resType); + setUseWorkingDirectory(useWorkingDirectory); + setWorkingDirectory(workingDirectory); + setCommand(command); + } + + + public CommandDataBasic(CommandDataBasic commandData) { + this(commandData.getName(), commandData.getResourceType(), commandData.isUseWorkingDirectory(), commandData.getWorkingDirectory(), commandData.getCommand()); + } + + public CommandDataBasic() { + } + + public String getName() { + return name; + } + + public ResourceType getResourceType() { + return resourceType; + } + + public boolean isUseWorkingDirectory() { + return useWorkingDirectory; + } + + public String getWorkingDirectory() { + return workingDirectory; + } + + public String getCommand() { + return command; + } + + public void setName(String name) { + this.name = name; + } + + public void setResourceType(ResourceType resType) { + this.resourceType = resType; + } + + public void setUseWorkingDirectory(boolean useWorkingDirectory) { + this.useWorkingDirectory = useWorkingDirectory; + } + + public void setWorkingDirectory(String workingDirectory) { + if (workingDirectory != null) { + this.workingDirectory = workingDirectory; + } else { + this.workingDirectory = "${easyshell:container_loc}"; + } + } + + public void setCommand(String command) { + this.command = command; + } + + public boolean equals(Object object) { + if(!(object instanceof CommandDataBasic)) { + return false; + } + CommandDataBasic data = (CommandDataBasic)object; + if(data.getName().equals(this.getName()) && + data.getResourceType() == this.getResourceType() && + data.isUseWorkingDirectory() == this.isUseWorkingDirectory() && + data.getWorkingDirectory().equals(this.getWorkingDirectory()) && + data.getCommand().equals(this.getCommand()) + ) + { + return true; + } + return false; + } + + public boolean deserialize(Version version, String value, StringTokenizer tokenizer, String delimiter) { + if((value == null || value.length() <= 0) && tokenizer == null) { + return false; + } + if (tokenizer == null) { + tokenizer = new StringTokenizer(value,delimiter); + } + // set command data members + setName(tokenizer.nextToken()); + setResourceType(ResourceType.getFromEnum(tokenizer.nextToken())); + // handling of working directory + setUseWorkingDirectory(Boolean.valueOf(tokenizer.nextToken()).booleanValue()); + setWorkingDirectory(tokenizer.nextToken()); + // command + setCommand(tokenizer.nextToken()); + return true; + } + + public boolean deserialize(String value, StringTokenizer tokenizer, String delimiter) { + return deserialize(Version.actual, value, tokenizer, delimiter); + } + + public String serialize(Version version, String delimiter) { + String ret = getName() + delimiter; + ret += getResourceType().toString() + delimiter; + ret += Boolean.toString(isUseWorkingDirectory()) + delimiter; + ret += getWorkingDirectory() + delimiter; + ret += getCommand() + delimiter; + return ret; + } + + public String serialize(String delimiter) { + return serialize(Version.actual, delimiter); + } + +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java index 685b63c3..9d23c8ee 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDialog.java @@ -37,13 +37,13 @@ import de.anbos.eclipse.easyshell.plugin.Utils; import de.anbos.eclipse.easyshell.plugin.types.Category; import de.anbos.eclipse.easyshell.plugin.types.CommandType; +import de.anbos.eclipse.easyshell.plugin.types.PresetType; import de.anbos.eclipse.easyshell.plugin.types.ResourceType; import de.anbos.eclipse.easyshell.plugin.types.Variable; public class CommandDataDialog extends StatusDialog { private CommandData data; - private boolean edit; private Combo resourceTypeCombo; private Label categoryImage; private Combo categoryCombo; @@ -56,13 +56,12 @@ public class CommandDataDialog extends StatusDialog { @Override public void create() { super.create(); - getButton(IDialogConstants.OK_ID).setEnabled(edit); + getButton(IDialogConstants.OK_ID).setEnabled(true); } - public CommandDataDialog(Shell parent, CommandData data, String title, boolean edit) { + public CommandDataDialog(Shell parent, CommandData data, String title) { super(parent); this.data = data; - this.edit = edit; // do layout and title setShellStyle(getShellStyle() | SWT.MAX); // set title @@ -182,7 +181,7 @@ public void widgetDefaultSelected(SelectionEvent e) { } }); dirCheckBox.setToolTipText(Activator.getResourceString("easyshell.command.editor.dialog.button.tooltip.useworkdir")); - dirCheckBox.setEnabled(edit); + dirCheckBox.setEnabled(true); } private void createVariableLabel(Composite parent, String varText, String labelText) { @@ -247,17 +246,30 @@ private void refreshDirCheckBox() { } protected void okPressed() { - if (edit) { - if (!validateValues()) { - return; - } - data.setName(nameText.getText()); - data.setResourceType(ResourceType.getFromName(resourceTypeCombo.getText())); - data.setUseWorkingDirectory(dirCheckBox.getSelection()); - data.setWorkingDirectory(dirText.getText()); - data.setCategory(Category.getFromName(categoryCombo.getText())); - data.setCommandType(CommandType.getFromName(commandTypeCombo.getText())); - data.setCommand(valueText.getText()); + if (!validateValues()) { + return; + } + CommandDataBasic cmdDataBasic = new CommandDataBasic(nameText.getText(), ResourceType.getFromName(resourceTypeCombo.getText()), dirCheckBox.getSelection(), dirText.getText(), valueText.getText()); + switch(data.getPresetType()) { + case presetUser: + data.setBasicData(cmdDataBasic); + data.setCategory(Category.getFromName(categoryCombo.getText())); + data.setCommandType(CommandType.getFromName(commandTypeCombo.getText())); + break; + case presetPlugin: + if (data.checkIfUserDataOverridesPreset(cmdDataBasic)) { + data.addUserData(cmdDataBasic); + } + break; + case presetPluginAndUser: + if (data.checkIfUserDataOverridesPreset(cmdDataBasic)) { + data.setUserData(cmdDataBasic); + } else { + data.removeUserData(); + } + break; + default: + break; } super.okPressed(); } @@ -339,10 +351,10 @@ public void widgetDefaultSelected(SelectionEvent e) { for(int i = 0 ; i < items.length ; i++) { if(items[i].equals(this.data.getResourceType().getName())) { resourceTypeCombo.select(i); - return; + break; } } - resourceTypeCombo.setEnabled(edit); + resourceTypeCombo.setEnabled(true); } private void createCategoryCombo(Composite parent) { @@ -369,10 +381,10 @@ public void widgetDefaultSelected(SelectionEvent e) { for(int i = 0 ; i < items.length ; i++) { if(items[i].equals(this.data.getCategory().getName())) { categoryCombo.select(i); - return; + break; } } - categoryCombo.setEnabled(edit); + categoryCombo.setEnabled(data.getPresetType() == PresetType.presetUser); } private void createCommandTypeCombo(Composite parent) { @@ -399,10 +411,10 @@ public void widgetDefaultSelected(SelectionEvent e) { for(int i = 0 ; i < items.length ; i++) { if(items[i].equals(this.data.getCommandType().getName())) { commandTypeCombo.select(i); - return; + break; } } - commandTypeCombo.setEnabled(edit); + commandTypeCombo.setEnabled(data.getPresetType() == PresetType.presetUser); } private Text createTextField(Composite parent, String labelText, String editValue, boolean emptyLabel) { @@ -417,7 +429,7 @@ private Text createTextField(Composite parent, String labelText, String editValu Text text = new Text(parent,SWT.BORDER); text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); text.setText(editValue); - text.setEditable(edit); + text.setEditable(true); return text; } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataStore.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataStore.java index 4049a55d..a6dc0251 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataStore.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataStore.java @@ -55,7 +55,7 @@ private CommandDataList getUserCommands() { private CommandDataList getPresetCommands() { CommandDataList presetItems = new CommandDataList(); for (CommandData data : getDataList()) { - if (data.getPresetType() == PresetType.presetPlugin) { + if (data.getPresetType() == PresetType.presetPlugin || data.getPresetType() == PresetType.presetPluginAndUser) { presetItems.add(data); } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java index 753b5429..698ae750 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java @@ -222,8 +222,8 @@ private void createButtons(Composite pageComponent) { // buttons createNewButton(font, gridData, groupComponent); - createCopyButton(font, gridData, groupComponent); createEditButton(font, gridData, groupComponent); + createCopyButton(font, gridData, groupComponent); createRemoveButton(font, gridData, groupComponent); } @@ -266,18 +266,22 @@ public void doubleClick(DoubleClickEvent event) { public void selectionChanged(SelectionChangedEvent event) { IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection(); boolean selected = !selection.isEmpty(); - boolean presetSelected = false; + boolean presetSelectedOrNotEqualType = false; Iterator elements = selection.iterator(); + PresetType type = PresetType.presetUnknown; while (elements.hasNext()) { CommandData data = (CommandData) elements.next(); - if (data.getPresetType() == PresetType.presetPlugin) { - presetSelected = true; + if (type == PresetType.presetUnknown) { + type = data.getPresetType(); + } + if (data.getPresetType() == PresetType.presetPlugin || type != data.getPresetType()) { + presetSelectedOrNotEqualType = true; break; } } - addCopyButton.setEnabled(selected); editButton.setEnabled(selected); - removeButton.setEnabled(selected && !presetSelected); + addCopyButton.setEnabled(selected); + removeButton.setEnabled(selected && !presetSelectedOrNotEqualType); } }); @@ -390,7 +394,7 @@ private void addDialog(CommandData data, boolean copy) { if (copy) { title = Activator.getResourceString("easyshell.command.editor.dialog.title.copy"); } - CommandDataDialog dialog = new CommandDataDialog(getShell(), data, title, true); + CommandDataDialog dialog = new CommandDataDialog(getShell(), data, title); if (dialog.open() == Window.OK) { CommandDataStore.instance().add(data); refreshTableViewer(data); @@ -415,19 +419,15 @@ private void addCopyDialog() { private void editDialog() { IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection(); CommandData dataSelected = (CommandData)selection.getFirstElement(); - if (dataSelected.getPresetType() == PresetType.presetUser) { - CommandData dataNew = new CommandData(dataSelected, false); - dataNew.setPosition(dataSelected.getPosition()); - CommandDataDialog dialog = new CommandDataDialog(getShell(), dataNew, Activator.getResourceString("easyshell.command.editor.dialog.title.edit"), true); - if (dialog.open() == Window.OK) { - CommandDataStore.instance().replace(dataNew); - refreshTableViewer(dataNew); - } else { - dataNew = null; - } + CommandData dataNew = new CommandData(dataSelected, false); + dataNew.setPosition(dataSelected.getPosition()); + String title = MessageFormat.format(Activator.getResourceString("easyshell.command.editor.dialog.title.edit"), dataNew.getPresetType().getName()); + CommandDataDialog dialog = new CommandDataDialog(getShell(), dataNew, title); + if (dialog.open() == Window.OK) { + CommandDataStore.instance().replace(dataNew); + refreshTableViewer(dataNew); } else { - CommandDataDialog dialog = new CommandDataDialog(getShell(), dataSelected, Activator.getResourceString("easyshell.command.editor.dialog.title.show"), false); - dialog.open(); + dataNew = null; } } @@ -445,22 +445,42 @@ private void removeDialog() { } // ask user String commandNames = ""; + PresetType type = PresetType.presetUnknown; for (CommandData command : commands) { + if (type == PresetType.presetUnknown) { + type = command.getPresetType(); + } commandNames += command.getCommandAsComboName() + "\n"; } - String title = Activator.getResourceString("easyshell.command.page.dialog.remove.title"); - String question = MessageFormat.format(Activator.getResourceString("easyshell.command.page.dialog.remove.question"), - commandNames); + String title = null; + String question = null; + if (type == PresetType.presetPluginAndUser) { + title = Activator.getResourceString("easyshell.command.page.dialog.remove.user.title"); + question = MessageFormat.format( + Activator.getResourceString("easyshell.command.page.dialog.remove.user.question"), + commandNames); + } else { + title = Activator.getResourceString("easyshell.command.page.dialog.remove.title"); + question = MessageFormat.format( + Activator.getResourceString("easyshell.command.page.dialog.remove.question"), + commandNames); + } int dialogImageType = MessageDialog.QUESTION; if (menus.size() > 0) { dialogImageType = MessageDialog.WARNING; - title = Activator.getResourceString("easyshell.command.page.dialog.remove.menu.title"); String menuNames = ""; for (MenuData menu : menus) { menuNames += menu.getNameExpanded() + "\n"; } - question = MessageFormat.format(Activator.getResourceString("easyshell.command.page.dialog.remove.menu.question"), - commandNames, menuNames); + if (type == PresetType.presetPluginAndUser) { + title = Activator.getResourceString("easyshell.command.page.dialog.remove.menu.user.title"); + question = MessageFormat.format(Activator.getResourceString("easyshell.command.page.dialog.remove.menu.user.question"), + commandNames, menuNames); + } else { + title = Activator.getResourceString("easyshell.command.page.dialog.remove.menu.title"); + question = MessageFormat.format(Activator.getResourceString("easyshell.command.page.dialog.remove.menu.question"), + commandNames, menuNames); + } } MessageDialog dialog = new MessageDialog( null, title, null, question, @@ -469,14 +489,19 @@ private void removeDialog() { 1); // no is the default int result = dialog.open(); if (result == 0) { - if (menus.size() >= 0) { + if (menus.size() >= 0 && type == PresetType.presetUser) { for (MenuData menu : menus) { MenuDataStore.instance().delete(menu); } //MenuDataStore.instance().save(); } for (CommandData command : commands) { - CommandDataStore.instance().delete(command); + if (command.getPresetType() == PresetType.presetUser) { + CommandDataStore.instance().delete(command); + } else if (command.getPresetType() == PresetType.presetPluginAndUser) { + command.removeUserData(); + CommandDataStore.instance().replace(command); + } } tableViewer.refresh(); } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java index 91cf80df..f5ee33cb 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java @@ -145,10 +145,10 @@ public void modifyText(ModifyEvent e) { createCommandCombo(pageGroup2); createNewButton(font, pageGroup2, gridData2); // create input commandText field commandText = createTextField(pageGroup2, Activator.getResourceString("easyshell.menu.editor.dialog.label.command"), menuData.getCommandData().getCommand(), false); - createCopyButton(font, pageGroup2, gridData2); - createLabel(pageGroup2, "");createLabel(pageGroup2, ""); createEditButton(font, pageGroup2, gridData2); createLabel(pageGroup2, "");createLabel(pageGroup2, ""); + createCopyButton(font, pageGroup2, gridData2); + createLabel(pageGroup2, "");createLabel(pageGroup2, ""); createRemoveButton(font, pageGroup2, gridData2); // TODO: to be enabled again, see https://github.com/anb0s/EasyShell/issues/61 @@ -241,7 +241,7 @@ private void addDialog(CommandData data, boolean copy) { if (copy) { title = Activator.getResourceString("easyshell.command.editor.dialog.title.copy"); } - CommandDataDialog dialog = new CommandDataDialog(getShell(), data, title, true); + CommandDataDialog dialog = new CommandDataDialog(getShell(), data, title); if (dialog.open() == Window.OK) { addCommand(data); refreshCommandCombo(); @@ -259,19 +259,21 @@ private void addCommand(CommandData data) { private void replaceCommand(int index, CommandData data) { CommandDataStore.instance().replace(data); - //CommandDataStore.instance().save(); commandCombo.setItem(index, data.getCommandAsComboName()); commandCombo.select(index); } private void removeCommand(int index, CommandData data) { - CommandDataStore.instance().delete(data); - //CommandDataStore.instance().save(); - //cmdList.remove(data); // no need to search for data, use index instead: - cmdList.remove(index); - String[] names = getAllCommandsAsComboNames(cmdList); - commandCombo.setItems(names); - commandCombo.select(names.length-1); + if (data.getPresetType() == PresetType.presetUser) { + CommandDataStore.instance().delete(data); + cmdList.remove(index); + String[] names = getAllCommandsAsComboNames(cmdList); + commandCombo.setItems(names); + commandCombo.select(names.length-1); + } else if (data.getPresetType() == PresetType.presetPluginAndUser) { + data.removeUserData(); + replaceCommand(index, data); + } } private void addNewDialog() { @@ -289,19 +291,15 @@ private void addCopyDialog() { private void editDialog() { int index = commandCombo.getSelectionIndex(); CommandData dataSelected = cmdList.get(index); - if (dataSelected.getPresetType() == PresetType.presetUser) { - CommandData dataNew = new CommandData(dataSelected, false); - dataNew.setPosition(dataSelected.getPosition()); - CommandDataDialog dialog = new CommandDataDialog(getShell(), dataNew, Activator.getResourceString("easyshell.command.editor.dialog.title.edit"), true); - if (dialog.open() == Window.OK) { - replaceCommand(index, dataNew); - refreshCommandCombo(); - } else { - dataNew = null; - } + CommandData dataNew = new CommandData(dataSelected, false); + dataNew.setPosition(dataSelected.getPosition()); + String title = MessageFormat.format(Activator.getResourceString("easyshell.command.editor.dialog.title.edit"), dataNew.getPresetType().getName()); + CommandDataDialog dialog = new CommandDataDialog(getShell(), dataNew, title); + if (dialog.open() == Window.OK) { + replaceCommand(index, dataNew); + refreshCommandCombo(); } else { - CommandDataDialog dialog = new CommandDataDialog(getShell(), dataSelected, Activator.getResourceString("easyshell.command.editor.dialog.title.show"), false); - dialog.open(); + dataNew = null; } } @@ -318,20 +316,35 @@ private void removeDialog() { menus.remove(this.menuData); // ask user String commandNames = commandCombo.getItem(index); - String title = Activator.getResourceString("easyshell.menu.editor.dialog.title.remove"); - String question = MessageFormat.format( - Activator.getResourceString("easyshell.menu.editor.dialog.question.remove"), - commandNames); + String title = null; + String question = null; + if (data.getPresetType() == PresetType.presetPluginAndUser) { + title = Activator.getResourceString("easyshell.menu.editor.dialog.title.user.remove"); + question = MessageFormat.format( + Activator.getResourceString("easyshell.menu.editor.dialog.question.user.remove"), + commandNames); + } else { + title = Activator.getResourceString("easyshell.menu.editor.dialog.title.remove"); + question = MessageFormat.format( + Activator.getResourceString("easyshell.menu.editor.dialog.question.remove"), + commandNames); + } int dialogImageType = MessageDialog.QUESTION; if (menus.size() > 0) { dialogImageType = MessageDialog.WARNING; - title = Activator.getResourceString("easyshell.menu.editor.dialog.title.remove.menu"); String menuNames = ""; for (MenuData menu : menus) { menuNames += menu.getNameExpanded() + "\n"; } - question = MessageFormat.format(Activator.getResourceString("easyshell.menu.editor.dialog.question.remove.menu"), - commandNames, menuNames); + if (data.getPresetType() == PresetType.presetPluginAndUser) { + title = Activator.getResourceString("easyshell.menu.editor.dialog.title.remove.user.menu"); + question = MessageFormat.format(Activator.getResourceString("easyshell.menu.editor.dialog.question.remove.user.menu"), + commandNames, menuNames); + } else { + title = Activator.getResourceString("easyshell.menu.editor.dialog.title.remove.menu"); + question = MessageFormat.format(Activator.getResourceString("easyshell.menu.editor.dialog.question.remove.menu"), + commandNames, menuNames); + } } MessageDialog dialog = new MessageDialog( null, title, null, question, @@ -450,15 +463,15 @@ private void createCommandCombo(Composite parent) { public void widgetSelected(SelectionEvent e) { int index = commandCombo.getSelectionIndex(); //String text = commandCombo.getItem(index); - CommandData cmdData = cmdList.get(index); + CommandData cmdData = cmdList.get(index); menuData.setCommandId(cmdData.getId()); if (menuData.getNameType() != MenuNameType.menuNameTypeUser) { menuData.setNameTypeFromCategory(cmdData.getCategory()); } commandText.setText(menuData.getCommandData().getCommand()); - boolean isUserDefined = menuData.getCommandData().getPresetType() == PresetType.presetUser; - //editButton.setEnabled(isUserDefined); - removeButton.setEnabled(isUserDefined); + boolean presetSelected = menuData.getCommandData().getPresetType() == PresetType.presetPlugin; + //editButton.setEnabled(!presetSelected); + removeButton.setEnabled(!presetSelected); // updates & refreshes updateTypeComboSelection(); refreshNameTypeCombo(); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java index 4970d378..32cc58d0 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java @@ -203,8 +203,8 @@ private void createButtons(Composite pageComponent) { // buttons createNewButton(font, gridData, groupComponent); - createCopyButton(font, gridData, groupComponent); createEditButton(font, gridData, groupComponent); + createCopyButton(font, gridData, groupComponent); createRemoveButton(font, gridData, groupComponent); createUpButton(font, gridData, groupComponent); createDownButton(font, gridData, groupComponent); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/PresetType.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/PresetType.java index 64a4465a..cd602215 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/PresetType.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/PresetType.java @@ -17,7 +17,8 @@ public enum PresetType { presetUnknown(-1, "Unknown"), presetPlugin(0, "Plugin"), - presetUser(1, "User"); + presetUser(1, "User"), + presetPluginAndUser(2, "Plugin+User"); // attributes private final int id; private final String name; From 018556126e7436172b6430e1d27d29186eb66ddd Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Thu, 15 Sep 2016 21:24:30 +0200 Subject: [PATCH 50/73] fixed warnings Signed-off-by: Andre Bossert --- .../easyshell/plugin/actions/Action.java | 8 +++--- .../plugin/commands/DefineCommands.java | 1 - .../easyshell/plugin/legacy/PrefsV1_4.java | 3 +++ .../easyshell/plugin/legacy/PrefsV1_5.java | 25 ----------------- .../plugin/preferences/CommandPage.java | 6 +++-- .../plugin/preferences/MenuData.java | 27 ++++++++++++++----- .../plugin/preferences/MenuPage.java | 7 ++--- 7 files changed, 34 insertions(+), 43 deletions(-) diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/Action.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/Action.java index b05f5dbc..5ce137a1 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/Action.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/actions/Action.java @@ -23,7 +23,7 @@ public class Action implements IAction { private String id; public Action(String myId) { - id = myId; + setId(myId); } @Override @@ -70,8 +70,7 @@ public ImageDescriptor getHoverImageDescriptor() { @Override public String getId() { - // TODO Auto-generated method stub - return null; + return id; } @Override @@ -184,8 +183,7 @@ public void setHoverImageDescriptor(ImageDescriptor newImage) { @Override public void setId(String id) { - // TODO Auto-generated method stub - + this.id = id; } @Override diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java index 20b330d7..7da4d080 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java @@ -12,7 +12,6 @@ package de.anbos.eclipse.easyshell.plugin.commands; import java.util.HashMap; -import java.util.List; import java.util.Map; import org.eclipse.swt.SWT; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/PrefsV1_4.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/PrefsV1_4.java index 4d02a52e..3fb630c7 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/PrefsV1_4.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/PrefsV1_4.java @@ -143,6 +143,7 @@ private enum Command { public int getId() { return id; } + @SuppressWarnings("unused") public String getOS() { return os; } @@ -152,6 +153,7 @@ public String getConsole() { public String getExplorer() { return explorer; } + @SuppressWarnings("unused") public String getLabel() { return label; } @@ -167,6 +169,7 @@ public String getExploreCmd() { public String getCopyPathCmd() { return copyPathCmd; } + @SuppressWarnings("unused") static Command getFromId(int id) { Command ret = cmdUnknown; for(int i = 0; i < Command.values().length; i++) { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/PrefsV1_5.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/PrefsV1_5.java index bd0b2ecf..f05a61bd 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/PrefsV1_5.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/legacy/PrefsV1_5.java @@ -408,11 +408,6 @@ private static Command getProperCommand() { case desktopXfce: cmd = Command.cmdXfceTermThunar; break; default: cmd = Command.cmdUnknown; } - // try to detect the default file browser - if (desktop != LinuxDesktop.desktopUnknown) { - String fileBrowser = detectLinuxDefaultFileBrowser(); - //Activator.getDefault().sysout(true, "Detected linux (Unix) default file browser: >" + fileBrowser + "<"); - } } return cmd; } @@ -456,26 +451,6 @@ private static boolean isCde() { return false; } - /** - * detects programs from $DESKTOP_SESSION - */ - private static String detectLinuxDefaultFileBrowser() { - ArrayList command = new ArrayList(); - command.add("xdg-mime"); - command.add("query"); - command.add("default"); - command.add("inode/directory"); - // fill the map - Map fileBrowsers = new HashMap(); - fileBrowsers.put("nemo.desktop", "nemo"); - // execute - String fileBrowser = isExpectedCommandOutput(command, fileBrowsers, true); - if (fileBrowser != null && !fileBrowser.isEmpty()) { - return (String)fileBrowsers.get(fileBrowser); - } - return null; - } - /** * Detects which desktop is used on a unix / linux system. * diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java index 698ae750..f8bb5824 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java @@ -26,7 +26,7 @@ import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TableViewerColumn; import org.eclipse.jface.viewers.Viewer; -import org.eclipse.jface.viewers.ViewerSorter; +import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyAdapter; @@ -285,7 +285,8 @@ public void selectionChanged(SelectionChangedEvent event) { } }); - tableViewer.setSorter(new ViewerSorter() { + tableViewer.setComparator(new ViewerComparator() { + @Override public int compare(Viewer viewer, Object object1, Object object2) { if (!(object1 instanceof CommandData) || !(object2 instanceof CommandData)) { return super.compare(viewer, object1, object2); @@ -303,6 +304,7 @@ public int compare(Viewer viewer, Object object1, Object object2) { } return super.compare(viewer, object1, object2); } + @Override public boolean isSorterProperty(Object element, String property) { return true; } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java index 0c8d1718..c71fa4f2 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java @@ -213,19 +213,32 @@ public void setNameTypeFromCategory() { } public void setNameTypeFromCategory(Category category) { - switch(category) { - case categoryDefault: setNameType(MenuNameType.menuNameTypeDefaultApplication); + switch (category) { + case categoryDefault: + setNameType(MenuNameType.menuNameTypeDefaultApplication); break; - case categoryOpen: setNameType(MenuNameType.menuNameTypeOpenHere); + case categoryOpen: + setNameType(MenuNameType.menuNameTypeOpenHere); break; - case categoryRun: setNameType(MenuNameType.menuNameTypeGeneric2); + case categoryRun: + setNameType(MenuNameType.menuNameTypeGeneric2); break; - case categoryExplore: setNameType(MenuNameType.menuNameTypeShowIn); + case categoryExplore: + setNameType(MenuNameType.menuNameTypeShowIn); break; - case categoryClipboard: setNameType(MenuNameType.menuNameTypeCopyToClipboard); + case categoryClipboard: + setNameType(MenuNameType.menuNameTypeCopyToClipboard); + break; + case categoryOther: + setNameType(MenuNameType.menuNameTypeGeneric1); + break; + case categoryUnknown: + setNameType(MenuNameType.menuNameTypeGeneric1); + break; + default: + setNameType(MenuNameType.menuNameTypeGeneric1); break; } - } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java index 32cc58d0..c813b9aa 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuPage.java @@ -28,7 +28,7 @@ import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TableViewerColumn; import org.eclipse.jface.viewers.Viewer; -import org.eclipse.jface.viewers.ViewerSorter; +import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyAdapter; @@ -265,7 +265,8 @@ public void selectionChanged(SelectionChangedEvent event) { } }); - tableViewer.setSorter(new ViewerSorter() { + tableViewer.setComparator(new ViewerComparator() { + @Override public int compare(Viewer viewer, Object object1, Object object2) { if (!(object1 instanceof MenuData) || !(object2 instanceof MenuData)) { return super.compare(viewer, object1, object2); @@ -283,7 +284,7 @@ public int compare(Viewer viewer, Object object1, Object object2) { } return super.compare(viewer, object1, object2); } - + @Override public boolean isSorterProperty(Object element, String property) { return true; } From a1c11e82e7a503014d85c1842c830d5c32436fd0 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Thu, 15 Sep 2016 21:24:35 +0200 Subject: [PATCH 51/73] fixed target platform definitions and set to Neon 4.6 Signed-off-by: Andre Bossert --- platform/Eclipse-3.8.target | 2 +- platform/Eclipse-4.4.target | 2 +- platform/Eclipse-4.5.target | 4 ++-- platform/Eclipse-4.6.target | 2 +- pom.xml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/platform/Eclipse-3.8.target b/platform/Eclipse-3.8.target index d391aef2..c145931f 100644 --- a/platform/Eclipse-3.8.target +++ b/platform/Eclipse-3.8.target @@ -2,7 +2,7 @@ - + diff --git a/platform/Eclipse-4.4.target b/platform/Eclipse-4.4.target index eec49c78..ee854f33 100644 --- a/platform/Eclipse-4.4.target +++ b/platform/Eclipse-4.4.target @@ -2,7 +2,7 @@ - + diff --git a/platform/Eclipse-4.5.target b/platform/Eclipse-4.5.target index 363dddce..7cc14be9 100644 --- a/platform/Eclipse-4.5.target +++ b/platform/Eclipse-4.5.target @@ -1,8 +1,8 @@ - - + + diff --git a/platform/Eclipse-4.6.target b/platform/Eclipse-4.6.target index 18969b1b..ea7a6829 100644 --- a/platform/Eclipse-4.6.target +++ b/platform/Eclipse-4.6.target @@ -2,7 +2,7 @@ - + diff --git a/pom.xml b/pom.xml index 84f76aaa..0589ebfe 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ 0.24.0 - Eclipse-4.5 + Eclipse-4.6 UTF-8 From fcd5181888e5af752e9b3372e24f36a8d77aeef7 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Sun, 18 Sep 2016 13:41:48 +0200 Subject: [PATCH 52/73] #40 add support for path conversions Signed-off-by: Andre Bossert --- .../plugin/DynamicVariableResolver.java | 30 +++- .../eclipse/easyshell/plugin/Resource.java | 52 +++++-- .../easyshell/plugin/UIMessages.properties | 4 +- .../CommandDataDefaultCollection.java | 7 +- .../plugin/preferences/CommandDataDialog.java | 76 +++++++--- .../easyshell/plugin/types/Converter.java | 140 ++++++++++++++++++ .../easyshell/plugin/types/Converters.java | 27 ++++ .../easyshell/plugin/types/IConverter.java | 16 ++ .../eclipse/easyshell/plugin/types/OS.java | 3 +- .../easyshell/plugin/types/Variable.java | 64 ++++++-- 10 files changed, 373 insertions(+), 46 deletions(-) create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/types/Converter.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/types/Converters.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/types/IConverter.java diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/DynamicVariableResolver.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/DynamicVariableResolver.java index 83ba9d13..71dccdc8 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/DynamicVariableResolver.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/DynamicVariableResolver.java @@ -15,7 +15,12 @@ import org.eclipse.core.variables.IDynamicVariable; import org.eclipse.core.variables.IDynamicVariableResolver; +import de.anbos.eclipse.easyshell.plugin.types.Converter; +import de.anbos.eclipse.easyshell.plugin.types.Converters; +import de.anbos.eclipse.easyshell.plugin.types.IConverter; +import de.anbos.eclipse.easyshell.plugin.types.IVariableResolver; import de.anbos.eclipse.easyshell.plugin.types.Quotes; +import de.anbos.eclipse.easyshell.plugin.types.Variable; import de.anbos.eclipse.easyshell.plugin.types.Variables; public class DynamicVariableResolver implements IDynamicVariableResolver { @@ -35,7 +40,30 @@ public String resolveValue(IDynamicVariable variable, String argument) } private String handleOwnVariable(String argument) { - return autoQuotes(Variables.getMap().get(argument).resolve(resource)); + String variableArg = argument; + String converterName = "Unknown"; + int converterIndex = argument.indexOf(":"); + if (converterIndex != -1) { + // first try to find a variable that has same pattern + // e.g. var:conv = var_conv + String variableSubs = variableArg.replace(":", "_"); + IVariableResolver variableSubsResolver = Variables.getMap().get(variableSubs); + if (variableSubsResolver != null) { + variableArg = variableSubs; + } else { + variableArg = argument.substring(0, converterIndex); + converterName = argument.substring(converterIndex + 1); + } + } + IConverter converter = Converters.getMap().get(converterName); + if (converter == null) { + converter = Converter.converterUnknown.getConverterImpl(); + } + IVariableResolver resolver = Variables.getMap().get(variableArg); + if (resolver == null) { + resolver = Variable.varUnknown.getResolver(); + } + return autoQuotes(converter.convert(resolver.resolve(resource))); } private String handleEclipseVariable(String variable, String argument) { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/Resource.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/Resource.java index dab5ee5e..ebc32c5e 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/Resource.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/Resource.java @@ -22,6 +22,8 @@ import org.eclipse.jdt.core.JavaCore; import org.osgi.framework.Bundle; +import de.anbos.eclipse.easyshell.plugin.types.OS; + public class Resource { // internal @@ -30,7 +32,6 @@ public class Resource { // resolved private String projectName = Activator.getResourceString("easyshell.plugin.name"); - static private String lineSeparator = null; //Activator.logDebug("full_path : >" + fullPath + "<"); //Activator.logDebug("parent_path: >" + parentPath + "<"); @@ -91,8 +92,8 @@ public String getContainerName() { return file.getParentFile().getName(); } else { return file.getName(); - } - } + } + } } public String getContainerPath() { @@ -118,7 +119,7 @@ public String getResourceName() { resourceName = ""; } else {*/ return file.getName(); - //} + //} } } @@ -150,22 +151,46 @@ public String getProjectPath() { return ""; } - public String getLineSeparator() { - if (lineSeparator == null) { - lineSeparator = System.getProperty("line.separator"); + public String getLineSeparator(OS os) { + switch(os) { + case osUnix: + case osLinux: + case osMacOSX: + return new String ("\n"); + case osWindows: + return new String ("\r\n"); + default: + return System.getProperty("line.separator"); } - return lineSeparator; } - public String getFileSeparator() { - return System.getProperty("file.separator"); + public String getPathSeparator(OS os) { + switch(os) { + case osUnix: + case osLinux: + case osMacOSX: + return new String (":"); + case osWindows: + return new String (";"); + default: + return File.pathSeparator; //System.getProperty("path.separator"); + } } - public String getPathSeparator() { - return System.getProperty("path.separator"); + public String getFileSeparator(OS os) { + switch(os) { + case osUnix: + case osLinux: + case osMacOSX: + return new String ("/"); + case osWindows: + return new String ("\\"); + default: + return File.separator; //System.getProperty("file.separator"); + } } - public String getFullQualifiedName() { + public String getFullQualifiedName() { if (resource != null) { Bundle bundle = Platform.getBundle("org.eclipse.jdt.core"); if (bundle != null) { @@ -186,6 +211,7 @@ public String getFullQualifiedName() { public String getFullQualifiedPathName() { String fqcn = ""; if (resource != null) { + return resource.getFullPath().toString(); /* String[] segments = iRes.getProjectRelativePath().segments(); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties index 14d26f9f..6540653d 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/UIMessages.properties @@ -103,7 +103,9 @@ easyshell.command.editor.dialog.title.edit=Edit command defined by {0} easyshell.command.editor.dialog.title.group1=Command easyshell.command.editor.dialog.tooltip.group1=Add your command here easyshell.command.editor.dialog.title.group2=Usable variables -easyshell.command.editor.dialog.tooltip.group2=Double click at variable copies it to clipboard +easyshell.command.editor.dialog.tooltip.group2=Double click at variable name copies it to clipboard +easyshell.command.editor.dialog.title.group3=Usable converters +easyshell.command.editor.dialog.tooltip.group3=Double click at converter name copies it to clipboard easyshell.command.editor.dialog.error.title.incompletedata=Missing or wrong parameters easyshell.command.editor.dialog.error.text.resource=Please choose a valid resource type easyshell.command.editor.dialog.error.text.category=Please choose a valid category diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java index f9475948..e87d9d21 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandDataDefaultCollection.java @@ -185,7 +185,7 @@ private void addAllOSCommands() { "\"${easyshell:qualified_name}\"${easyshell:line_separator}")); // Clipboard - Variables Test String varTestString = ""; - for(int i=1;i getFromOS(OS os) { + List ret = new ArrayList<>(); + for(int i = 0; i < Converter.values().length; i++) { + if (Converter.values()[i].getOS() == os) { + ret.add(Converter.values()[i]); + } + } + return ret; + } + public static Converter getFromName(String name) { + Converter ret = converterUnknown; + for(int i = 0; i < Converter.values().length; i++) { + if (Converter.values()[i].getName().equals(name)) { + ret = Converter.values()[i]; + break; + } + } + return ret; + } + public static Converter getFromEnum(String name) { + return Converter.valueOf(name); + } + public static int getFirstIndex() { + return 0; + } +}; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Converters.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Converters.java new file mode 100644 index 00000000..8f51cfb9 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Converters.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.types; + +import java.util.HashMap; +import java.util.Map; + +public class Converters { + static Map map = new HashMap(); + public static Map getMap() { + return map; + } + static { + for(int i=0;i getNamesAsList() { } return list; } - public IVariableResolver getResolver() { - return resolver; + public static int getFirstIndex() { + return 0; } } From 8471f6cc9fd49fba251baa6ecbc7c49590e9dcb8 Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Mon, 19 Sep 2016 19:50:59 +0200 Subject: [PATCH 53/73] #46 [v2.0] [regression] add key bindings again #47 [v2.0] add popup menu with key binding support - renamed categoryOther to categoryUser - added new short cuts: - EasyShell All : Alt + E - EasyShell Open: Alt + O - EasyShell Run : Alt + R - EasyShell Explore: Alt + X - EasyShell Clipboard: Alt + C - EasyShell Default: Alt + D - EasyShell User: Alt + U Signed-off-by: Andre Bossert --- plugin/plugin.xml | 108 ++++++++++++- .../eclipse/easyshell/plugin/Constants.java | 2 +- .../plugin/commands/CategoryPopupDialog.java | 151 ++++++++++++++++++ .../plugin/commands/DefineCommands.java | 2 +- .../easyshell/plugin/handlers/All.java | 68 ++++++++ .../easyshell/plugin/handlers/Clipboard.java | 24 +++ .../easyshell/plugin/handlers/Default.java | 24 +++ .../{CommandHandler.java => Execute.java} | 2 +- .../easyshell/plugin/handlers/Explore.java | 24 +++ .../easyshell/plugin/handlers/Open.java | 24 +++ .../easyshell/plugin/handlers/Run.java | 24 +++ .../easyshell/plugin/handlers/User.java | 24 +++ .../plugin/preferences/CommandData.java | 6 +- .../plugin/preferences/CommandPage.java | 2 +- .../plugin/preferences/MenuData.java | 2 +- .../plugin/preferences/MenuDataDialog.java | 2 +- .../plugin/preferences/MenuDataStore.java | 9 +- .../easyshell/plugin/types/Category.java | 4 +- 18 files changed, 490 insertions(+), 12 deletions(-) create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/commands/CategoryPopupDialog.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/All.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/Clipboard.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/Default.java rename plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/{CommandHandler.java => Execute.java} (97%) create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/Explore.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/Open.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/Run.java create mode 100644 plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/User.java diff --git a/plugin/plugin.xml b/plugin/plugin.xml index e59efa93..43534fff 100644 --- a/plugin/plugin.xml +++ b/plugin/plugin.xml @@ -28,13 +28,81 @@ optional="false"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -107,5 +175,43 @@ supportsArgument="true"> + + + + + + + + + + + + + + + + diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/Constants.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/Constants.java index 54c8c06a..1f7583ca 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/Constants.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/Constants.java @@ -24,7 +24,7 @@ public interface Constants { public static final String IMAGE_RUN = "run_exc.gif"; public static final String IMAGE_EXPLORE = "fldr_obj.gif"; public static final String IMAGE_CLIPBOARD = "copy.gif"; - public static final String IMAGE_OTHER = "environment_obj.gif"; + public static final String IMAGE_USER = "environment_obj.gif"; // Preferences public static final String PREF_COMMANDS_PRESET = "COMMANDS_PRESET"; diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/CategoryPopupDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/CategoryPopupDialog.java new file mode 100644 index 00000000..5ad0f0a0 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/CategoryPopupDialog.java @@ -0,0 +1,151 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.commands; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.commands.Command; +import org.eclipse.core.commands.ParameterizedCommand; +import org.eclipse.jface.bindings.TriggerSequence; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.commands.ICommandService; +import org.eclipse.ui.handlers.IHandlerService; +import org.eclipse.ui.keys.IBindingService; + +import de.anbos.eclipse.easyshell.plugin.preferences.MenuData; +import de.anbos.eclipse.easyshell.plugin.preferences.MenuDataList; + +public class CategoryPopupDialog extends org.eclipse.jface.dialogs.PopupDialog implements SelectionListener, KeyListener { + + private IWorkbenchPart activePart; + private MenuDataList menuDataList; + private org.eclipse.swt.widgets.List listView; + List chars; + + public CategoryPopupDialog(Shell parent, IWorkbenchPart activePart, MenuDataList menuDataList) + { + super(parent, INFOPOPUP_SHELLSTYLE, true, false, false, false, false, null, null); + this.activePart = activePart; + this.menuDataList = menuDataList; + chars = new ArrayList(); + for (Character ch='0';ch<='9';ch++) { + chars.add(ch); + } + for (Character ch='a';ch<='z';ch++) { + chars.add(ch); + } + } + + void init(IWorkbenchPart activePart, MenuDataList menuDataList) { + this.activePart = activePart; + this.menuDataList = menuDataList; + } + + @Override + protected Control createDialogArea(Composite parent) { + final Composite listViewComposite = (Composite)super.createDialogArea(parent); + listView = new org.eclipse.swt.widgets.List(listViewComposite, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL); + listView.addSelectionListener(this); + listView.addKeyListener(this); + for (int i=0;i= menuDataList.size()) { + return; + } + listView.setSelection(index); + try { + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + MenuData item = menuDataList.get(index); + this.close(); + // get command + //ICommandService service = (ICommandService)PlatformUI.getWorkbench().getService(ICommandService.class); + ICommandService commandService = (ICommandService)activePart.getSite().getService(ICommandService.class); + Command command = commandService != null ? commandService.getCommand("de.anbos.eclipse.easyshell.plugin.commands.execute") : null; + // get handler service + IHandlerService handlerService = (IHandlerService)activePart.getSite().getService(IHandlerService.class); + IBindingService bindingService = (IBindingService)activePart.getSite().getService(IBindingService.class); + TriggerSequence[] triggerSequenceArray = bindingService.getActiveBindingsFor("de.anbos.eclipse.easyshell.plugin.commands.open"); + if (command != null && handlerService != null) { + Map commandParamametersMap = new HashMap(); + commandParamametersMap.put("de.anbos.eclipse.easyshell.plugin.commands.parameter.type", + item.getCommandData().getCommandType().getAction()); + commandParamametersMap.put("de.anbos.eclipse.easyshell.plugin.commands.parameter.value", + item.getCommandData().getCommand()); + commandParamametersMap.put("de.anbos.eclipse.easyshell.plugin.commands.parameter.workingdir", + item.getCommandData().isUseWorkingDirectory() ? item.getCommandData().getWorkingDirectory() : ""); + ParameterizedCommand paramCommand = ParameterizedCommand.generateCommand(command, commandParamametersMap); + try { + handlerService.executeCommand(paramCommand, null); + } catch (Exception ex) { + } + } + } + + @Override + public void keyPressed(KeyEvent e) { + if (e.keyCode == SWT.CR || e.keyCode == SWT.KEYPAD_CR) { + executeCommand(-1); + } else if (((e.stateMask & SWT.ALT) == 0) && ((e.stateMask & SWT.CTRL) == 0) && ((e.stateMask & SWT.SHIFT) == 0)) { + if(e.keyCode >= '0' && e.keyCode <= '9') { //check digit + executeCommand(e.keyCode - '0'); + } else if(e.keyCode >= 'a' && e.keyCode <= 'z') { //check character + executeCommand((e.keyCode - 'a') + ('9' - '0' + 1)); + } + } + } + + @Override + public void keyReleased(KeyEvent e) { + // TODO Auto-generated method stub + + } + + @Override + public void widgetSelected(SelectionEvent e) { + // TODO Auto-generated method stub + + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + if (e.widget != listView) { + return; + } + executeCommand(-1); + } + +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java index 7da4d080..ad3c7b52 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/commands/DefineCommands.java @@ -35,7 +35,6 @@ public DefineCommands() { @Override public void createContributionItems(IServiceLocator serviceLocator, IContributionRoot additions) { - // load the preferences CommandDataStore.instance().load(); MenuDataStore.instance().load(); @@ -68,5 +67,6 @@ private void addItem(IServiceLocator serviceLocator, IContributionRoot additions CommandContributionItem item = new CommandContributionItem(param); item.setVisible(true); additions.addContributionItem(item, null); + } } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/All.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/All.java new file mode 100644 index 00000000..7ae7da8f --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/All.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.handlers; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.handlers.HandlerUtil; + +import de.anbos.eclipse.easyshell.plugin.commands.CategoryPopupDialog; +import de.anbos.eclipse.easyshell.plugin.preferences.CommandDataStore; +import de.anbos.eclipse.easyshell.plugin.preferences.MenuDataList; +import de.anbos.eclipse.easyshell.plugin.preferences.MenuDataStore; +import de.anbos.eclipse.easyshell.plugin.types.Category; + +public class All extends AbstractHandler { + + private CategoryPopupDialog dialog; + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException + { + if (dialog != null) + { + dialog.close(); + dialog = null; + } + //create and open a new dialog + IWorkbenchPart activePart = HandlerUtil.getActivePart(event); + // load the preferences + dialog = new CategoryPopupDialog(Display.getCurrent().getActiveShell(), activePart, getMenuDataList()); + dialog.open(); + return null; + } + + public MenuDataList getMenuDataList(Category category) { + CommandDataStore.instance().load(); + MenuDataStore.instance().load(); + MenuDataList menuDataList = MenuDataStore.instance().getEnabledCommandMenuDataListByCategory(category); + return menuDataList; + } + + public MenuDataList getMenuDataList() { + return getMenuDataList(Category.categoryUnknown); + } + + @Override + public boolean isEnabled() { + return true; + } + + @Override + public boolean isHandled() { + return true; + } + +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/Clipboard.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/Clipboard.java new file mode 100644 index 00000000..617f9a65 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/Clipboard.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.handlers; + +import de.anbos.eclipse.easyshell.plugin.preferences.MenuDataList; +import de.anbos.eclipse.easyshell.plugin.types.Category; + +public class Clipboard extends All { + + @Override + public MenuDataList getMenuDataList() { + return super.getMenuDataList(Category.categoryClipboard); + } + +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/Default.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/Default.java new file mode 100644 index 00000000..c9e745ca --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/Default.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.handlers; + +import de.anbos.eclipse.easyshell.plugin.preferences.MenuDataList; +import de.anbos.eclipse.easyshell.plugin.types.Category; + +public class Default extends All { + + @Override + public MenuDataList getMenuDataList() { + return super.getMenuDataList(Category.categoryDefault); + } + +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/CommandHandler.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/Execute.java similarity index 97% rename from plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/CommandHandler.java rename to plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/Execute.java index b7e58581..5ba11298 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/CommandHandler.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/Execute.java @@ -23,7 +23,7 @@ import de.anbos.eclipse.easyshell.plugin.actions.ActionDelegate; import de.anbos.eclipse.easyshell.plugin.types.CommandType; -public class CommandHandler extends AbstractHandler { +public class Execute extends AbstractHandler { public Object execute(ExecutionEvent event) throws ExecutionException { IWorkbenchPart activePart = HandlerUtil.getActivePart(event); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/Explore.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/Explore.java new file mode 100644 index 00000000..d59b08ea --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/Explore.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.handlers; + +import de.anbos.eclipse.easyshell.plugin.preferences.MenuDataList; +import de.anbos.eclipse.easyshell.plugin.types.Category; + +public class Explore extends All { + + @Override + public MenuDataList getMenuDataList() { + return super.getMenuDataList(Category.categoryExplore); + } + +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/Open.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/Open.java new file mode 100644 index 00000000..a825f74c --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/Open.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.handlers; + +import de.anbos.eclipse.easyshell.plugin.preferences.MenuDataList; +import de.anbos.eclipse.easyshell.plugin.types.Category; + +public class Open extends All { + + @Override + public MenuDataList getMenuDataList() { + return super.getMenuDataList(Category.categoryOpen); + } + +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/Run.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/Run.java new file mode 100644 index 00000000..09625519 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/Run.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.handlers; + +import de.anbos.eclipse.easyshell.plugin.preferences.MenuDataList; +import de.anbos.eclipse.easyshell.plugin.types.Category; + +public class Run extends All { + + @Override + public MenuDataList getMenuDataList() { + return super.getMenuDataList(Category.categoryRun); + } + +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/User.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/User.java new file mode 100644 index 00000000..7a2d9645 --- /dev/null +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/handlers/User.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2014 - 2016 Andre Bossert. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andre Bossert - initial API and implementation and/or initial documentation + *******************************************************************************/ + +package de.anbos.eclipse.easyshell.plugin.handlers; + +import de.anbos.eclipse.easyshell.plugin.preferences.MenuDataList; +import de.anbos.eclipse.easyshell.plugin.types.Category; + +public class User extends All { + + @Override + public MenuDataList getMenuDataList() { + return super.getMenuDataList(Category.categoryUser); + } + +} diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java index fa8a9efe..34db253d 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandData.java @@ -259,7 +259,11 @@ public boolean deserialize(Version version, String value, StringTokenizer tokeni if (version.getId() >= Version.v2_0_003.getId()) { basicData.setUseWorkingDirectory(Boolean.valueOf(tokenizer.nextToken()).booleanValue()); basicData.setWorkingDirectory(tokenizer.nextToken()); - setCategory(Category.getFromEnum(tokenizer.nextToken())); + String categoryStr = tokenizer.nextToken(); + if (version.getId() < Version.v2_0_005.getId() && categoryStr.equals("categoryOther")) { + categoryStr = "categoryUser"; + } + setCategory(Category.getFromEnum(categoryStr)); setCommandType(CommandType.getFromEnum(tokenizer.nextToken())); } else { basicData.setUseWorkingDirectory(false); diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java index f8bb5824..6a1717e9 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/CommandPage.java @@ -406,7 +406,7 @@ private void addDialog(CommandData data, boolean copy) { } private void addNewDialog() { - CommandData dataNew = new CommandData(null, PresetType.presetUser, Utils.getOS(), "MyNewCommand", ResourceType.resourceTypeFileOrDirectory, Category.categoryOther, CommandType.commandTypeExecute, "my_new_command"); + CommandData dataNew = new CommandData(null, PresetType.presetUser, Utils.getOS(), "MyNewCommand", ResourceType.resourceTypeFileOrDirectory, Category.categoryUser, CommandType.commandTypeExecute, "my_new_command"); addDialog(dataNew, false); } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java index c71fa4f2..421e884c 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuData.java @@ -229,7 +229,7 @@ public void setNameTypeFromCategory(Category category) { case categoryClipboard: setNameType(MenuNameType.menuNameTypeCopyToClipboard); break; - case categoryOther: + case categoryUser: setNameType(MenuNameType.menuNameTypeGeneric1); break; case categoryUnknown: diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java index f5ee33cb..118d288d 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataDialog.java @@ -277,7 +277,7 @@ private void removeCommand(int index, CommandData data) { } private void addNewDialog() { - CommandData data = new CommandData(null, PresetType.presetUser, Utils.getOS(), "MyNewCommand", ResourceType.resourceTypeFileOrDirectory, Category.categoryOther, CommandType.commandTypeExecute, "my_new_command"); + CommandData data = new CommandData(null, PresetType.presetUser, Utils.getOS(), "MyNewCommand", ResourceType.resourceTypeFileOrDirectory, Category.categoryUser, CommandType.commandTypeExecute, "my_new_command"); addDialog(data, false); } diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java index 1ddc7d29..d6b72b1f 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/preferences/MenuDataStore.java @@ -19,6 +19,7 @@ import de.anbos.eclipse.easyshell.plugin.Activator; import de.anbos.eclipse.easyshell.plugin.Constants; +import de.anbos.eclipse.easyshell.plugin.types.Category; public class MenuDataStore extends DataStore { @@ -55,18 +56,22 @@ public MenuData[] getCommandMenuDataArray() { return allArray; } - public MenuDataList getEnabledCommandMenuDataList() { + public MenuDataList getEnabledCommandMenuDataListByCategory(Category category) { MenuDataList checkedItems = new MenuDataList(); Iterator dataIterator = getDataList().iterator(); while(dataIterator.hasNext()) { MenuData data = (MenuData)dataIterator.next(); - if(data.isEnabled()) { + if(data.isEnabled() && (category == Category.categoryUnknown || data.getCommandData().getCategory() == category)) { checkedItems.add(data); } } return checkedItems; } + public MenuDataList getEnabledCommandMenuDataList() { + return getEnabledCommandMenuDataListByCategory(Category.categoryUnknown); + } + public MenuData[] getEnabledCommandMenuDataArray() { MenuDataList checkedItems = getEnabledCommandMenuDataList(); if(checkedItems.size() <= 0) { diff --git a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Category.java b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Category.java index a6ab7512..30d141e4 100644 --- a/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Category.java +++ b/plugin/src/de/anbos/eclipse/easyshell/plugin/types/Category.java @@ -25,7 +25,7 @@ public enum Category { categoryRun(2, "Run", Constants.IMAGE_RUN), categoryExplore(3, "Explore", Constants.IMAGE_EXPLORE), categoryClipboard(4, "Clipboard", Constants.IMAGE_CLIPBOARD), - categoryOther(5, "Other", Constants.IMAGE_OTHER); + categoryUser(5, "User", Constants.IMAGE_USER); // attributes private final int id; private final String name; @@ -75,7 +75,7 @@ public static Category getFromDeprecatedCommandTypeEnum(String name) { map.put("commandTypeRun", categoryRun); map.put("commandTypeExplore", categoryExplore); map.put("commandTypeClipboard", categoryClipboard); - map.put("commandTypeOther", categoryOther); + map.put("commandTypeOther", categoryUser); // find the key for(String key: map.keySet()) { if (name.equals(key)) { From e2847ed6fb392d351e1ac2e81945a96b6dd4c4bf Mon Sep 17 00:00:00 2001 From: Andre Bossert Date: Mon, 19 Sep 2016 21:00:11 +0200 Subject: [PATCH 54/73] [v2.0] issues found in beta 4 - #40 add support for path conversions - #46 [v2.0] [regression] add key bindings again - #47 [v2.0] add popup menu with key binding support - #55 [v2.0] migration support from legacy EasyShell v1.x - #81 [v2.0] "Copy Full Path to Clipboard" missing at Mac OS X - #82 [v2.0] ${easyshell:resource_loc} missing in "usable variables" - #83 [v2.0] rework "Copy..." and "Show/Edit.." buttons in command dialog Signed-off-by: Andre Bossert --- .../2.0/2.0.0.v20160919-1856/artifacts.jar | Bin 0 -> 733 bytes .../2.0/2.0.0.v20160919-1856/content.jar | Bin 0 -> 5794 bytes ....easyshell.feature_2.0.0.v20160919-1856.jar | Bin 0 -> 5136 bytes ...e.easyshell.plugin_2.0.0.v20160919-1856.jar | Bin 0 -> 194377 bytes .../updates/testing/2.0/compositeArtifacts.xml | 5 +++-- site/updates/testing/2.0/compositeContent.xml | 5 +++-- 6 files changed, 6 insertions(+), 4 deletions(-) create mode 100644 site/updates/testing/2.0/2.0.0.v20160919-1856/artifacts.jar create mode 100644 site/updates/testing/2.0/2.0.0.v20160919-1856/content.jar create mode 100644 site/updates/testing/2.0/2.0.0.v20160919-1856/features/de.anbos.eclipse.easyshell.feature_2.0.0.v20160919-1856.jar create mode 100644 site/updates/testing/2.0/2.0.0.v20160919-1856/plugins/de.anbos.eclipse.easyshell.plugin_2.0.0.v20160919-1856.jar diff --git a/site/updates/testing/2.0/2.0.0.v20160919-1856/artifacts.jar b/site/updates/testing/2.0/2.0.0.v20160919-1856/artifacts.jar new file mode 100644 index 0000000000000000000000000000000000000000..3038c61c4c9e52bb27e72b2371bb64f42b990bcc GIT binary patch literal 733 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 literal 0 HcmV?d00001 diff --git a/site/updates/testing/2.0/2.0.0.v20160919-1856/features/de.anbos.eclipse.easyshell.feature_2.0.0.v20160919-1856.jar b/site/updates/testing/2.0/2.0.0.v20160919-1856/features/de.anbos.eclipse.easyshell.feature_2.0.0.v20160919-1856.jar new file mode 100644 index 0000000000000000000000000000000000000000..b22b96d5d234932fc0e2ba5733d20505401f95ef GIT binary patch literal 5136 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 literal 0 HcmV?d00001 diff --git a/site/updates/testing/2.0/2.0.0.v20160919-1856/plugins/de.anbos.eclipse.easyshell.plugin_2.0.0.v20160919-1856.jar b/site/updates/testing/2.0/2.0.0.v20160919-1856/plugins/de.anbos.eclipse.easyshell.plugin_2.0.0.v20160919-1856.jar new file mode 100644 index 0000000000000000000000000000000000000000..1f79ebd4d7b5284a7d47b2473a460a12d22826de GIT binary patch literal 194377 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

96xh!e#x7ff>Inpl<7>^9J@hdLUFA>ww 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