From b4c90af94926b9904ba2e75286339faad986c0bb Mon Sep 17 00:00:00 2001 From: Lyubomir Marinov Date: Wed, 28 Aug 2013 00:57:09 +0300 Subject: [PATCH] Implements an editor which allows the user to edit Jitsi's configuration properties from within the application. (Marin Dzhigarov) --- build.xml | 12 +- lib/felix.client.run.properties | 3 +- resources/languages/resources.properties | 12 + .../contactlist/ContactSearchFieldUI.java | 98 +++++++ .../gui/main/contactlist/SearchField.java | 227 ++++++++-------- .../desktoputil/plaf}/SearchFieldUI.java | 254 ++++++++---------- .../plugin/propertieseditor/ButtonsPanel.java | 158 +++++++++++ .../plugin/propertieseditor/Constants.java | 21 ++ .../propertieseditor/NewPropertyDialog.java | 179 ++++++++++++ .../PropertiesEditorActivator.java | 129 +++++++++ .../PropertiesEditorPanel.java | 137 ++++++++++ .../propertieseditor/PropsTableModel.java | 139 ++++++++++ .../plugin/propertieseditor/SearchField.java | 158 +++++++++++ .../propertieseditor/StartingPanel.java | 60 +++++ .../plugin/propertieseditor/WarningPanel.java | 98 +++++++ .../propertieseditor.manifest.mf | 22 ++ .../sip/communicator/util/UtilActivator.java | 1 - 17 files changed, 1455 insertions(+), 253 deletions(-) create mode 100644 src/net/java/sip/communicator/impl/gui/main/contactlist/ContactSearchFieldUI.java rename src/net/java/sip/communicator/{impl/gui/main/contactlist => plugin/desktoputil/plaf}/SearchFieldUI.java (82%) create mode 100644 src/net/java/sip/communicator/plugin/propertieseditor/ButtonsPanel.java create mode 100644 src/net/java/sip/communicator/plugin/propertieseditor/Constants.java create mode 100644 src/net/java/sip/communicator/plugin/propertieseditor/NewPropertyDialog.java create mode 100644 src/net/java/sip/communicator/plugin/propertieseditor/PropertiesEditorActivator.java create mode 100644 src/net/java/sip/communicator/plugin/propertieseditor/PropertiesEditorPanel.java create mode 100644 src/net/java/sip/communicator/plugin/propertieseditor/PropsTableModel.java create mode 100644 src/net/java/sip/communicator/plugin/propertieseditor/SearchField.java create mode 100644 src/net/java/sip/communicator/plugin/propertieseditor/StartingPanel.java create mode 100644 src/net/java/sip/communicator/plugin/propertieseditor/WarningPanel.java create mode 100644 src/net/java/sip/communicator/plugin/propertieseditor/propertieseditor.manifest.mf diff --git a/build.xml b/build.xml index 0ff32050b..96f19f8d5 100644 --- a/build.xml +++ b/build.xml @@ -1079,7 +1079,7 @@ bundle-globalshortcut,bundle-plugin-msofficecomm,bundle-libjitsi, bundle-customcontactactions, bundle-phonenumbercontactsource, bundle-demuxcontactsource, bundle-desktoputil, - bundle-globaldisplaydetails"/> + bundle-globaldisplaydetails,bundle-plugin-propertieseditor"/> @@ -2941,4 +2941,14 @@ javax.swing.event, javax.swing.border"/> prefix="net/java/sip/communicator/impl/globaldisplaydetails" /> + + + + + + + + diff --git a/lib/felix.client.run.properties b/lib/felix.client.run.properties index 7514ce040..44871116d 100644 --- a/lib/felix.client.run.properties +++ b/lib/felix.client.run.properties @@ -184,7 +184,8 @@ felix.auto.start.67= \ reference:file:sc-bundles/plugin-contactsourceconfig.jar \ reference:file:sc-bundles/plugin-certconfig.jar \ reference:file:sc-bundles/phonenumbercontactsource.jar \ - reference:file:sc-bundles/demuxcontactsource.jar + reference:file:sc-bundles/demuxcontactsource.jar \ + reference:file:sc-bundles/propertieseditor.jar # Level 68 is for profiler4j. Either don't use it or change the build.xml file # accordingly. diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties index 601863d19..96a10e60a 100644 --- a/resources/languages/resources.properties +++ b/resources/languages/resources.properties @@ -512,6 +512,7 @@ service.gui.UNKNOWN=Unknown user service.gui.UNKNOWN_STATUS=Unknown state service.gui.UNREGISTERED_MESSAGE=Unable to connect the following account: User name: {0}, Server name: {1}. You are currently offline. service.gui.USE_PROVISIONING=Use online provisioning +service.gui.VALUE=Value service.gui.VIDEO_CALL=&Video call service.gui.VIA=via service.gui.VIA_SMS=Via SMS @@ -1703,6 +1704,17 @@ plugin.certconfig.REVOCATION_OCSP_ENABLED=OCSP (Online Certificate Status Protoc # Phone number contact source plugin plugin.phonenumbercontactsource.DISPLAY_NAME=Phone numbers +# properties editor +plugin.propertieseditor.TITLE=Property Editor +plugin.propertieseditor.NEW_PROPERTY_TITLE=Add new property +plugin.propertieseditor.CHECK_BOX=Show this warning next time +plugin.propertieseditor.DESCRIPTION=The following button allows modifying Jitsi configuration properties. \ +Changing these advanced settings can be harmful to the stability, security, \ +and performance of this application. You should only continue if you are sure \ +of what you are doing. +plugin.propertieseditor.IM_AWARE=I am aware of the risks +plugin.propertieseditor.NEED_RESTART=Note: some properties might need a restart before new settings will take effect. + #Thunderbird address book plugin plugin.thunderbird.CONFIG_FORM_TITLE=Thunderbird plugin.thunderbird.ENABLED=Enabled diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactSearchFieldUI.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactSearchFieldUI.java new file mode 100644 index 000000000..256d70e71 --- /dev/null +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactSearchFieldUI.java @@ -0,0 +1,98 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.gui.main.contactlist; + +import java.awt.*; +import java.awt.event.*; + +import javax.swing.*; +import javax.swing.plaf.*; +import javax.swing.text.*; + +import net.java.sip.communicator.impl.gui.main.call.*; +import net.java.sip.communicator.plugin.desktoputil.plaf.*; +import net.java.sip.communicator.util.*; +import net.java.sip.communicator.util.skin.*; + +/** + * + * @author Marin Dzhigarov + */ +public class ContactSearchFieldUI + extends SearchFieldUI + implements Skinnable +{ + /** + * Creates a UI for a SearchFieldUI. + * + * @param c the text field + * @return the UI + */ + public static ComponentUI createUI(JComponent c) + { + return new ContactSearchFieldUI(); + } + + public ContactSearchFieldUI() + { + // Indicates if the big call button outside the search is enabled. + String callButtonEnabledString + = UtilActivator.getResources().getSettingsString( + "impl.gui.CALL_BUTTON_ENABLED"); + + if ((callButtonEnabledString != null) + && (callButtonEnabledString.length() > 0)) + { + // If the outside call button is enabled the call button in this + // search field is disabled. + isCallButtonEnabled + = !Boolean.parseBoolean(callButtonEnabledString); + } + + loadSkin(); + } + + /** + * Paints the background of the associated component. + * + * @param g the Graphics object used for painting + */ + @Override + protected void customPaintBackground(Graphics g) + { + isCallButtonEnabled = CallManager.getTelephonyProviders().size() > 0; + super.customPaintBackground(g); + } + + /** + * Creates a call when the mouse is clicked on the call icon. + * + * @param ev the mouse event that has prompted us to create the call. + */ + @Override + protected void updateCallIcon(MouseEvent ev) + { + super.updateCallIcon(ev); + + + if ((ev.getID() == MouseEvent.MOUSE_CLICKED) && isCallIconVisible) + { + Rectangle callButtonRect = getCallButtonRect(); + int x = ev.getX(); + int y = ev.getY(); + + if (callButtonRect.contains(x, y)) + { + JTextComponent c = getComponent(); + String searchText = c.getText(); + + if (searchText != null) + CallManager.createCall(searchText, c); + } + } + } +} diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/SearchField.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/SearchField.java index 42183c496..090207a94 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/SearchField.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/SearchField.java @@ -25,6 +25,7 @@ * * @author Yana Stamcheva * @author Adam Netocny + * @author Marin Dzhigarov */ public class SearchField extends SIPCommTextField @@ -35,37 +36,38 @@ public class SearchField /** * Class id key used in UIDefaults. */ - private static final String uiClassID = - SearchField.class.getName() + "FieldUI"; + private static final String uiClassID + = SearchField.class.getName() + "FieldUI"; /** * Adds the ui class to UIDefaults. */ static { - UIManager.getDefaults().put(uiClassID, - SearchFieldUI.class.getName()); + UIManager.getDefaults().put( + uiClassID, + ContactSearchFieldUI.class.getName()); } /** - * The main application window. + * The contact list on which we apply the filter. */ - private final MainFrame mainFrame; + private ContactList contactList; /** - * The contact list on which we apply the filter. + * The current filter query. */ - private ContactList contactList; + private FilterQuery currentFilterQuery = null; /** - * The filter to apply on search. + * The main application window. */ - private final ContactListSearchFilter searchFilter; + private final MainFrame mainFrame; /** - * The current filter query. + * The filter to apply on search. */ - private FilterQuery currentFilterQuery = null; + private final ContactListSearchFilter searchFilter; /** * Creates the SearchField. @@ -85,10 +87,11 @@ public SearchField( MainFrame frame, this.mainFrame = frame; this.searchFilter = searchFilter; - if(getUI() instanceof SearchFieldUI) + if (getUI() instanceof ContactSearchFieldUI) { - ((SearchFieldUI)getUI()).setDeleteButtonEnabled(true); - ((SearchFieldUI)getUI()).setCallButtonEnabled(isCallButtonEnabled); + ((ContactSearchFieldUI) getUI()).setDeleteButtonEnabled(true); + ((ContactSearchFieldUI) getUI()) + .setCallButtonEnabled(isCallButtonEnabled); } this.setBorder(null); @@ -115,28 +118,6 @@ public void actionPerformed(ActionEvent e) loadSkin(); } - /** - * Handles the change when a char has been inserted in the field. - */ - public void textInserted() - { - // Should explicitly check if there's a text, because the default text - // triggers also an insertUpdate event. - String filterString = this.getText(); - if (filterString == null || filterString.length() <= 0) - return; - - updateContactListView(); - } - - /** - * Handles the change when a char has been removed from the field. - */ - public void textRemoved() - { - updateContactListView(); - } - /** * Do not need this for the moment. * @param e the DocumentEvent that notified us @@ -144,52 +125,6 @@ public void textRemoved() @Override public void changedUpdate(DocumentEvent e) {} - /** - * Schedules an update if necessary. - */ - private void updateContactListView() - { - String filterString = getText(); - - boolean isDefaultFilter = false; - - searchFilter.setFilterString(filterString.trim()); - - // First finish the last filter. - if (currentFilterQuery != null) - filterQueryFinished(currentFilterQuery, true); - - if (filterString != null && filterString.length() > 0) - { - currentFilterQuery = contactList.applyFilter(searchFilter); - } - else - { - currentFilterQuery = contactList.applyDefaultFilter(); - isDefaultFilter = true; - } - - if (currentFilterQuery != null && !currentFilterQuery.isCanceled()) - { - // If we already have a result here we update the interface. - // In the case of default filter we don't need to know if the - // query has succeeded, as event if it isn't we would like to - // remove the unknown contact view. - if (isDefaultFilter || currentFilterQuery.isSucceeded()) - enableUnknownContactView(false); - else - // Otherwise we will listen for events for changes in status - // of this query. - currentFilterQuery.setQueryListener(this); - } - else - { - // If the query is null or is canceled, we would simply check the - // contact list content. - filterQueryFinished(currentFilterQuery, !contactList.isEmpty()); - } - } - /** * Sets the unknown contact view to the main contact list window. * @@ -208,16 +143,6 @@ public void run() }); } - /** - * Sets the contact list, in which the search is performed. - * - * @param contactList the contact list in which the search is performed - */ - public void setContactList(ContactList contactList) - { - this.contactList = contactList; - } - /** * Indicates that the given query has finished with failure, i.e. * no results for the filter were found. @@ -231,6 +156,24 @@ public void filterQueryFailed(FilterQuery query) filterQueryFinished(query, false); } + /** + * Performs all needed updates when a filter query has finished. + * + * @param query the query that has finished + * @param hasResults indicates if the query has results + */ + private void filterQueryFinished(FilterQuery query, boolean hasResults) + { + // If the unknown contact view was previously enabled, but we + // have found matching contacts we enter the normal view. + enableUnknownContactView(!hasResults); + + if (hasResults) + contactList.selectFirstContact(); + + query.setQueryListener(null); + } + /** * Indicates that the given query has finished with success, i.e. * the filter has returned results. @@ -244,15 +187,6 @@ public void filterQuerySucceeded(FilterQuery query) filterQueryFinished(query, true); } - /** - * Reloads text field UI defs. - */ - public void loadSkin() - { - if(getUI() instanceof SearchFieldUI) - ((SearchFieldUI)getUI()).loadSkin(); - } - /** * Returns the name of the L&F class that renders this component. * @@ -267,20 +201,89 @@ public String getUIClassID() } /** - * Performs all needed updates when a filter query has finished. + * Reloads text field UI defs. + */ + public void loadSkin() + { + if (getUI() instanceof ContactSearchFieldUI) + ((ContactSearchFieldUI) getUI()).loadSkin(); + } + + /** + * Sets the contact list, in which the search is performed. * - * @param query the query that has finished - * @param hasResults indicates if the query has results + * @param contactList the contact list in which the search is performed */ - private void filterQueryFinished(FilterQuery query, boolean hasResults) + public void setContactList(ContactList contactList) { - // If the unknown contact view was previously enabled, but we - // have found matching contacts we enter the normal view. - enableUnknownContactView(!hasResults); + this.contactList = contactList; + } - if (hasResults) - contactList.selectFirstContact(); + /** + * Handles the change when a char has been inserted in the field. + */ + public void textInserted() + { + // Should explicitly check if there's a text, because the default text + // triggers also an insertUpdate event. + String filterString = this.getText(); + if (filterString == null || filterString.length() <= 0) + return; - query.setQueryListener(null); + updateContactListView(); + } + + /** + * Handles the change when a char has been removed from the field. + */ + public void textRemoved() + { + updateContactListView(); + } + + /** + * Schedules an update if necessary. + */ + private void updateContactListView() + { + String filterString = getText(); + + boolean isDefaultFilter = false; + + searchFilter.setFilterString(filterString.trim()); + + // First finish the last filter. + if (currentFilterQuery != null) + filterQueryFinished(currentFilterQuery, true); + + if (filterString != null && filterString.length() > 0) + { + currentFilterQuery = contactList.applyFilter(searchFilter); + } + else + { + currentFilterQuery = contactList.applyDefaultFilter(); + isDefaultFilter = true; + } + + if (currentFilterQuery != null && !currentFilterQuery.isCanceled()) + { + // If we already have a result here we update the interface. + // In the case of default filter we don't need to know if the + // query has succeeded, as event if it isn't we would like to + // remove the unknown contact view. + if (isDefaultFilter || currentFilterQuery.isSucceeded()) + enableUnknownContactView(false); + else + // Otherwise we will listen for events for changes in status + // of this query. + currentFilterQuery.setQueryListener(this); + } + else + { + // If the query is null or is canceled, we would simply check the + // contact list content. + filterQueryFinished(currentFilterQuery, !contactList.isEmpty()); + } } } diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/SearchFieldUI.java b/src/net/java/sip/communicator/plugin/desktoputil/plaf/SearchFieldUI.java similarity index 82% rename from src/net/java/sip/communicator/impl/gui/main/contactlist/SearchFieldUI.java rename to src/net/java/sip/communicator/plugin/desktoputil/plaf/SearchFieldUI.java index 2b0297b67..53b7d842b 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/SearchFieldUI.java +++ b/src/net/java/sip/communicator/plugin/desktoputil/plaf/SearchFieldUI.java @@ -4,7 +4,7 @@ * Distributable under LGPL license. * See terms of license at gnu.org. */ -package net.java.sip.communicator.impl.gui.main.contactlist; +package net.java.sip.communicator.plugin.desktoputil.plaf; import java.awt.*; import java.awt.event.*; @@ -13,13 +13,11 @@ import javax.swing.plaf.*; import javax.swing.text.*; -import net.java.sip.communicator.impl.gui.*; -import net.java.sip.communicator.impl.gui.main.call.*; import net.java.sip.communicator.plugin.desktoputil.*; -import net.java.sip.communicator.plugin.desktoputil.plaf.*; -import net.java.sip.communicator.util.*; import net.java.sip.communicator.util.skin.*; +import org.jitsi.service.resources.*; + /** * The SearchTextFieldUI is the one responsible for the search field * look & feel. It draws a search icon inside the field and adjusts the bounds @@ -27,15 +25,22 @@ * * @author Yana Stamcheva * @author Adam Netocny + * @author Marin Dzhigarov */ public class SearchFieldUI extends SIPCommTextFieldUI implements Skinnable { /** - * The icon indicating that this is a search field. + * Creates a UI for a SearchFieldUI. + * + * @param c the text field + * @return the UI */ - private ImageIcon searchIcon; + public static ComponentUI createUI(JComponent c) + { + return new SearchFieldUI(); + } /** * The default icon of the call button. @@ -43,9 +48,9 @@ public class SearchFieldUI private Image callIcon; /** - * The separator icon shown between the call icon and the close. + * The pressed icon of the call button. */ - private Image separatorIcon; + private Image callPressedIcon; /** * The roll over icon of the call button. @@ -53,76 +58,49 @@ public class SearchFieldUI private Image callRolloverIcon; /** - * The pressed icon of the call button. + * The call button tool tip string. */ - private Image callPressedIcon; + private final String callString = DesktopUtilActivator.getResources() + .getI18NString("service.gui.CALL"); /** - * Indicates if the mouse is currently over the call button. + * Indicates if the call button is enabled in this search field. */ - private boolean isCallMouseOver = false; + protected boolean isCallButtonEnabled = true; /** - * Indicates if the mouse is currently over the call button. + * Indicates if the call icon is currently visible. */ - private boolean isCallMousePressed = false; + protected boolean isCallIconVisible = false; /** - * The call button tool tip string. + * Indicates if the mouse is currently over the call button. */ - private final String callString - = GuiActivator.getResources().getI18NString("service.gui.CALL"); + private boolean isCallMouseOver = false; /** - * Indicates if the call icon is currently visible. + * Indicates if the mouse is currently over the call button. */ - private boolean isCallIconVisible = false; + private boolean isCallMousePressed = false; /** - * Indicates if the call button is enabled in this search field. + * The icon indicating that this is a search field. */ - private boolean isCallButtonEnabled = true; + private ImageIcon searchIcon; /** - * Creates a SIPCommTextFieldUI. + * The separator icon shown between the call icon and the close. */ - public SearchFieldUI() - { - // Indicates if the big call button outside the search is enabled. - String callButtonEnabledString = UtilActivator.getResources() - .getSettingsString("impl.gui.CALL_BUTTON_ENABLED"); - - if (callButtonEnabledString != null - && callButtonEnabledString.length() > 0) - { - // If the outside call button is enabled the call button in this - // search field is disabled. - isCallButtonEnabled - = !new Boolean(callButtonEnabledString).booleanValue(); - } - - loadSkin(); - } + private Image separatorIcon; /** - * Enables/disabled the call button in the search field. - * - * @param isEnabled indicates if the call button is enabled + * Creates a GenericSearchFieldUI. */ - public void setCallButtonEnabled(boolean isEnabled) + public SearchFieldUI() { - this.isCallButtonEnabled = isEnabled; - } + isCallButtonEnabled = false; - /** - * Implements parent paintSafely method and enables antialiasing. - * @param g the Graphics object that notified us - */ - @Override - protected void paintSafely(Graphics g) - { - customPaintBackground(g); - super.paintSafely(g); + loadSkin(); } /** @@ -144,11 +122,10 @@ protected void customPaintBackground(Graphics g) int dy = (c.getY() + c.getHeight()) / 2 - searchIcon.getIconHeight()/2; - g2.drawImage(searchIcon.getImage(), 3, dy + 1, null); + g2.drawImage(searchIcon.getImage(), 3, dy, null); if (c.getText() != null && c.getText().length() > 0 - && CallManager.getTelephonyProviders().size() > 0 && isCallButtonEnabled) { // Paint call button. @@ -180,6 +157,25 @@ else if (isCallMouseOver) } } + /** + * Calculates the call button rectangle. + * + * @return the call button rectangle + */ + protected Rectangle getCallButtonRect() + { + Component c = getComponent(); + Rectangle rect = c.getBounds(); + + int dx = getDeleteButtonRect().x - callRolloverIcon.getWidth(null) - 8; + int dy = (rect.y + rect.height) / 2 - callRolloverIcon.getHeight(null)/2; + + return new Rectangle( dx, + dy, + callRolloverIcon.getWidth(null), + callRolloverIcon.getHeight(null)); + } + /** * If we are in the case of disabled delete button, we simply call the * parent implementation of this method, otherwise we recalculate the editor @@ -210,6 +206,32 @@ protected Rectangle getVisibleEditorRect() return null; } + /** + * Reloads UI icons. + */ + @Override + public void loadSkin() + { + super.loadSkin(); + + ResourceManagementService r = DesktopUtilActivator.getResources(); + + searchIcon = r.getImage("service.gui.icons.SEARCH_ICON"); + if (isCallButtonEnabled) + { + callIcon + = r.getImage("service.gui.buttons.SEARCH_CALL_ICON").getImage(); + callRolloverIcon + = r.getImage("service.gui.buttons.SEARCH_CALL_ROLLOVER_ICON") + .getImage(); + callPressedIcon + = r.getImage("service.gui.buttons.SEARCH_CALL_PRESSED_ICON") + .getImage(); + separatorIcon + = r.getImage("service.gui.icons.SEARCH_SEPARATOR").getImage(); + } + } + /** * Updates the call button when the mouse was clicked. * @param e the MouseEvent that notified us of the click @@ -223,6 +245,19 @@ public void mouseClicked(MouseEvent e) updateCallIcon(e); } + /** + * Updates the delete icon when the mouse is dragged over. + * @param e the MouseEvent that notified us + */ + @Override + public void mouseDragged(MouseEvent e) + { + super.mouseDragged(e); + + if(isCallButtonEnabled) + updateCallIcon(e); + } + /** * Updates the call button when the mouse is enters the component area. * @param e the MouseEvent that notified us @@ -249,6 +284,19 @@ public void mouseExited(MouseEvent e) updateCallIcon(e); } + /** + * Updates the delete icon when the mouse is moved over. + * @param e the MouseEvent that notified us + */ + @Override + public void mouseMoved(MouseEvent e) + { + super.mouseMoved(e); + + if(isCallButtonEnabled) + updateCallIcon(e); + } + @Override public void mousePressed(MouseEvent e) { @@ -268,29 +316,24 @@ public void mouseReleased(MouseEvent e) } /** - * Updates the delete icon when the mouse is dragged over. - * @param e the MouseEvent that notified us + * Implements parent paintSafely method and enables antialiasing. + * @param g the Graphics object that notified us */ @Override - public void mouseDragged(MouseEvent e) + protected void paintSafely(Graphics g) { - super.mouseDragged(e); - - if(isCallButtonEnabled) - updateCallIcon(e); + customPaintBackground(g); + super.paintSafely(g); } /** - * Updates the delete icon when the mouse is moved over. - * @param e the MouseEvent that notified us + * Enables/disabled the call button in the search field. + * + * @param isEnabled indicates if the call button is enabled */ - @Override - public void mouseMoved(MouseEvent e) + public void setCallButtonEnabled(boolean isEnabled) { - super.mouseMoved(e); - - if(isCallButtonEnabled) - updateCallIcon(e); + this.isCallButtonEnabled = isEnabled; } /** @@ -301,7 +344,7 @@ public void mouseMoved(MouseEvent e) * @param evt the mouse event that has prompted us to update the delete * icon. */ - private void updateCallIcon(MouseEvent evt) + protected void updateCallIcon(MouseEvent evt) { int x = evt.getX(); int y = evt.getY(); @@ -336,12 +379,6 @@ private void updateCallIcon(MouseEvent evt) // Update the default cursor. getComponent().setCursor(Cursor.getDefaultCursor()); - - // Perform call action when the call button is clicked. - if (evt.getID() == MouseEvent.MOUSE_CLICKED) - { - CallManager.createCall(searchText, c); - } } else { @@ -359,63 +396,4 @@ private void updateCallIcon(MouseEvent evt) getComponent().repaint(); } - - /** - * Calculates the call button rectangle. - * - * @return the call button rectangle - */ - protected Rectangle getCallButtonRect() - { - Component c = getComponent(); - Rectangle rect = c.getBounds(); - - int dx = getDeleteButtonRect().x - callRolloverIcon.getWidth(null) - 8; - int dy = (rect.y + rect.height) / 2 - callRolloverIcon.getHeight(null)/2; - - return new Rectangle( dx, - dy, - callRolloverIcon.getWidth(null), - callRolloverIcon.getHeight(null)); - } - - /** - * Reloads UI icons. - */ - @Override - public void loadSkin() - { - super.loadSkin(); - - searchIcon = UtilActivator.getResources() - .getImage("service.gui.icons.SEARCH_ICON"); - - if (isCallButtonEnabled) - { - callIcon = UtilActivator.getResources() - .getImage("service.gui.buttons.SEARCH_CALL_ICON").getImage(); - - callRolloverIcon = UtilActivator.getResources() - .getImage("service.gui.buttons.SEARCH_CALL_ROLLOVER_ICON") - .getImage(); - - callPressedIcon = UtilActivator.getResources() - .getImage("service.gui.buttons.SEARCH_CALL_PRESSED_ICON") - .getImage(); - - separatorIcon = UtilActivator.getResources() - .getImage("service.gui.icons.SEARCH_SEPARATOR").getImage(); - } - } - - /** - * Creates a UI for a SearchFieldUI. - * - * @param c the text field - * @return the UI - */ - public static ComponentUI createUI(JComponent c) - { - return new SearchFieldUI(); - } } diff --git a/src/net/java/sip/communicator/plugin/propertieseditor/ButtonsPanel.java b/src/net/java/sip/communicator/plugin/propertieseditor/ButtonsPanel.java new file mode 100644 index 000000000..cd667dea7 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/propertieseditor/ButtonsPanel.java @@ -0,0 +1,158 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ + +package net.java.sip.communicator.plugin.propertieseditor; + +import java.awt.*; +import java.awt.event.*; + +import javax.swing.*; + +import net.java.sip.communicator.plugin.desktoputil.*; + +import org.jitsi.service.configuration.*; +import org.jitsi.service.resources.*; + +/** + * The panel containing all buttons for the PropertiesEditorPanel. + * + * @author Marin Dzhigarov + */ +public class ButtonsPanel + extends TransparentPanel + implements ActionListener +{ + + /** + * Serial version UID. + */ + private static final long serialVersionUID = 1L; + + private ConfigurationService confService + = PropertiesEditorActivator.getConfigurationService(); + + private ResourceManagementService resourceManagementService + = PropertiesEditorActivator.getResourceManagementService(); + + /** + * The delete button. + */ + private JButton deleteButton = new JButton( + resourceManagementService.getI18NString("service.gui.DELETE")); + + /** + * The new button. + */ + private JButton newButton = new JButton( + resourceManagementService.getI18NString("service.gui.NEW")); + + /** + * The panel, containing all buttons. + */ + private JPanel buttonsPanel + = new TransparentPanel(new GridLayout(0, 1, 8, 8)); + + /** + * The props table. + */ + private JTable propsTable; + + /** + * Instance of the search box panel. + */ + private SearchField searchField; + + /** + * Creates an instance of ButtonsPanel. + * @param propsTable the table containing all properties. + * @param searchBox the search box panel containing the search box text + * field. + */ + public ButtonsPanel(JTable propsTable, SearchField searchField) + { + this.propsTable = propsTable; + + this.searchField = searchField; + + this.setLayout(new BorderLayout()); + + this.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); + + this.newButton.setOpaque(false); + this.deleteButton.setOpaque(false); + + this.buttonsPanel.add(newButton); + this.buttonsPanel.add(deleteButton); + + this.add(buttonsPanel, BorderLayout.NORTH); + + this.newButton.addActionListener(this); + this.deleteButton.addActionListener(this); + + //default as nothing is selected + defaultButtonState(); + } + + /** + * Default state of buttons, as nothing is selected + */ + public void defaultButtonState() + { + enableDeleteButton(false); + } + + /** + * Enable or disable the delete button. + * + * @param enable TRUE - to enable the delete button, FALSE - to disable it + */ + public void enableDeleteButton(boolean enable) + { + this.deleteButton.setEnabled(enable); + } + + /** + * Performs corresponding actions, when a button is pressed. + * @param e the ActionEvent that notified us + */ + public void actionPerformed(ActionEvent e) + { + JButton sourceButton = (JButton) e.getSource(); + + if (sourceButton.equals(newButton)) + { + NewPropertyDialog dialog = new NewPropertyDialog(); + + dialog.pack(); + dialog.setLocation( + Toolkit.getDefaultToolkit().getScreenSize().width/2 + - dialog.getWidth()/2, + Toolkit.getDefaultToolkit().getScreenSize().height/2 + - dialog.getHeight()/2 + ); + + dialog.setVisible(true); + + } else if (sourceButton.equals(deleteButton)) + { + int viewRow = propsTable.getSelectedRow(); + int modelRow = + propsTable.convertRowIndexToModel(viewRow); + String selectedProperty + = (String)propsTable.getModel().getValueAt(modelRow, 0); + confService.removeProperty(selectedProperty); + propsTable.clearSelection(); + defaultButtonState(); + /** + * Resets the text in the search box text field in order to fire + * a new value change event for the FilterRow to update the view. + */ + String text = searchField.getText(); + searchField.setText(text); + } + } +} diff --git a/src/net/java/sip/communicator/plugin/propertieseditor/Constants.java b/src/net/java/sip/communicator/plugin/propertieseditor/Constants.java new file mode 100644 index 000000000..e903b43c3 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/propertieseditor/Constants.java @@ -0,0 +1,21 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. See terms of license at gnu.org. + */ +package net.java.sip.communicator.plugin.propertieseditor; + +/** + * The Constants of this package. + * + * @author Marin Dzhigarov + * + */ +public class Constants +{ + /** + * Property indicating whether or not to show the WarningPanel + */ + public static String SHOW_WARNING_MSG_PROP = + "net.java.sip.communicator.plugin.propertieseditor.showWarningMsg"; +} diff --git a/src/net/java/sip/communicator/plugin/propertieseditor/NewPropertyDialog.java b/src/net/java/sip/communicator/plugin/propertieseditor/NewPropertyDialog.java new file mode 100644 index 000000000..4025070dc --- /dev/null +++ b/src/net/java/sip/communicator/plugin/propertieseditor/NewPropertyDialog.java @@ -0,0 +1,179 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. See terms of license at gnu.org. + */ +package net.java.sip.communicator.plugin.propertieseditor; + +import java.awt.*; +import java.awt.event.*; + +import javax.swing.*; +import javax.swing.event.*; + +import net.java.sip.communicator.plugin.desktoputil.*; + +import org.jitsi.service.configuration.*; +import org.jitsi.service.resources.*; + +/** + * @author Marin Dzhigarov + */ +public class NewPropertyDialog + extends SIPCommDialog + implements ActionListener +{ + + /** + * Serial version UID. + */ + private static final long serialVersionUID = 1L; + + private ConfigurationService confService = PropertiesEditorActivator + .getConfigurationService(); + + private ResourceManagementService resourceManagementService = + PropertiesEditorActivator.getResourceManagementService(); + + /** + * The ok button. + */ + private JButton okButton = new JButton( + resourceManagementService.getI18NString("service.gui.OK")); + + /** + * The cancel button. + */ + private JButton cancelButton = new JButton( + resourceManagementService.getI18NString("service.gui.CANCEL")); + + /** + * The property name text field. + */ + private JTextField propertyNameTextField = new JTextField(); + + /** + * The property value text field. + */ + private JTextField propertyValueTextField = new JTextField(); + + /** + * The property name label. + */ + private JLabel propertyNameLabel = new JLabel( + resourceManagementService.getI18NString("service.gui.NAME") + ": "); + + /** + * The property value label. + */ + private JLabel propertyValueLabel = new JLabel( + resourceManagementService.getI18NString("service.gui.VALUE") + ": "); + + /** + * The panel containing all buttons. + */ + private JPanel buttonsPanel = new TransparentPanel(new FlowLayout( + FlowLayout.CENTER)); + + /** + * The panel containing the property value and name panels. + */ + private JPanel dataPanel = new TransparentPanel(new GridBagLayout()); + + /** + * Creates an instance of NewPropertyDialog. + */ + public NewPropertyDialog() + { + setTitle(resourceManagementService + .getI18NString("plugin.propertieseditor.NEW_PROPERTY_TITLE")); + JPanel fields = new TransparentPanel(new BorderLayout()); + fields.setPreferredSize(new Dimension(450, 150)); + + this.getContentPane().add(fields); + + fields.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); + fields.add(dataPanel, BorderLayout.NORTH); + fields.add(buttonsPanel, BorderLayout.SOUTH); + + this.buttonsPanel.add(okButton); + this.buttonsPanel.add(cancelButton); + okButton.setEnabled(false); + + this.okButton.addActionListener(this); + this.cancelButton.addActionListener(this); + + GridBagConstraints first = new GridBagConstraints(); + first.gridx = 0; + first.gridy = 0; + first.weightx = 0; + first.anchor = GridBagConstraints.LINE_START; + first.gridwidth = 1; + first.insets = new Insets(2, 4, 2, 4); + first.fill = GridBagConstraints.HORIZONTAL; + + GridBagConstraints second = new GridBagConstraints(); + second.gridx = 1; + second.gridy = 0; + second.weightx = 2; + second.anchor = GridBagConstraints.LINE_START; + second.gridwidth = 1; // GridBagConstraints.REMAINDER; + second.insets = first.insets; + second.fill = GridBagConstraints.HORIZONTAL; + + dataPanel.add(propertyNameLabel, first); + dataPanel.add(propertyNameTextField, second); + + first.gridy = ++second.gridy; + + dataPanel.add(propertyValueLabel, first); + dataPanel.add(propertyValueTextField, second); + + propertyNameTextField.getDocument().addDocumentListener( + new DocumentListener() + { + public void insertUpdate(DocumentEvent e) + { + okButton.setEnabled(true); + } + + public void removeUpdate(DocumentEvent e) + { + if (propertyNameTextField.getText().length() == 0) + okButton.setEnabled(false); + } + + public void changedUpdate(DocumentEvent e) + { + } + }); + } + + /** + * Performs corresponding actions, when a button is pressed. + * + * @param e the ActionEvent that notified us + */ + public void actionPerformed(ActionEvent e) + { + JButton sourceButton = (JButton) e.getSource(); + + if (sourceButton.equals(okButton)) + { + confService.setProperty(propertyNameTextField.getText(), + propertyValueTextField.getText()); + } + dispose(); + } + + /** + * Presses programmatically the cancel button, when Esc key is pressed. + * + * @param isEscaped indicates if the Esc button was pressed on close + */ + protected void close(boolean isEscaped) + { + cancelButton.doClick(); + } + +} \ No newline at end of file diff --git a/src/net/java/sip/communicator/plugin/propertieseditor/PropertiesEditorActivator.java b/src/net/java/sip/communicator/plugin/propertieseditor/PropertiesEditorActivator.java new file mode 100644 index 000000000..a96394341 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/propertieseditor/PropertiesEditorActivator.java @@ -0,0 +1,129 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.plugin.propertieseditor; + +import org.jitsi.service.configuration.*; +import org.jitsi.service.resources.ResourceManagementService; + +import java.util.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.util.*; +import org.osgi.framework.*; + +/** + * The BundleActivator of the PropertiesEditor plugin. + * + * @author Marin Dzhigarov + * @author Pawel Domas + */ +public class PropertiesEditorActivator + implements BundleActivator +{ + + /** + * The bundle context. + */ + public static BundleContext bundleContext; + + /** + * Starts this bundle and adds the + * PropertiesEditorPanel contained in it to the configuration + * window obtained from the UIService. + * @param bc the BundleContext + * @throws Exception if one of the operation executed in the start method + * fails + */ + public void start(BundleContext bc) throws Exception + { + bundleContext = bc; + Dictionary properties = new Hashtable(); + properties.put(ConfigurationForm.FORM_TYPE, + ConfigurationForm.ADVANCED_TYPE); + bundleContext.registerService( + ConfigurationForm.class.getName(), + new LazyConfigurationForm( + StartingPanel.class.getName(), + getClass().getClassLoader(), + "", + "plugin.propertieseditor.TITLE", + 1002, true), + properties); + } + + /** + * Stops this bundles. + * @param bc the BundleContext + * @throws Exception if one of the operation executed in the stop method + * fails + */ + public void stop(BundleContext bc) throws Exception {} + + /** + * The ui service + */ + private static UIService uiService; + + /** + * Returns the UIService obtained from the bundle context. + * + * @return the UIService obtained from the bundle context. + */ + public static UIService getUIService() + { + if (uiService == null) + { + ServiceReference uiReference = + bundleContext.getServiceReference(UIService.class.getName()); + + uiService = + (UIService) bundleContext.getService(uiReference); + } + + return uiService; + } + + /** + * The configuration service. + */ + private static ConfigurationService configService; + + /** + * Returns the ConfigurationService obtained from the bundle context. + * + * @return the ConfigurationService obtained from the bundle context. + */ + public static ConfigurationService getConfigurationService() + { + if (configService == null) + { + configService = ServiceUtils.getService( + bundleContext, + ConfigurationService.class); + } + return configService; + } + + /** + * The resource management service. + */ + private static ResourceManagementService resourceManagementService; + + + /** + * Returns the ResourceManagementService obtained from the bundle context. + * + * @return the ResourceManagementService obtained from the bundle context. + */ + public static ResourceManagementService getResourceManagementService() { + if (resourceManagementService == null) { + resourceManagementService = ServiceUtils.getService( + bundleContext, + ResourceManagementService.class); + } + return resourceManagementService; + } +} \ No newline at end of file diff --git a/src/net/java/sip/communicator/plugin/propertieseditor/PropertiesEditorPanel.java b/src/net/java/sip/communicator/plugin/propertieseditor/PropertiesEditorPanel.java new file mode 100644 index 000000000..a589fb234 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/propertieseditor/PropertiesEditorPanel.java @@ -0,0 +1,137 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. See terms of license at gnu.org. + */ + +package net.java.sip.communicator.plugin.propertieseditor; + +import java.awt.*; + +import javax.swing.*; +import javax.swing.event.*; +import javax.swing.table.*; + +import net.java.sip.communicator.plugin.desktoputil.*; + +import org.jitsi.service.resources.*; + +/** + * @author Marin Dzhigarov + * @author Pawel Domas + * + */ +public class PropertiesEditorPanel + extends TransparentPanel + +{ + /** + * Serial version UID. + */ + private static final long serialVersionUID = 1L; + + private ResourceManagementService resourceManagementService = + PropertiesEditorActivator.getResourceManagementService(); + + /** + * The panel containing the props table and the buttons panel + */ + private JPanel centerPanel; + + /** + * The props table. + */ + private JTable propsTable; + + /** + * The buttons panel. + */ + private ButtonsPanel buttonsPanel; + + /** + * Creates an instance PropertiesEditorPanel. + */ + public PropertiesEditorPanel() + { + super(new BorderLayout()); + setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); + + /** + * Instantiates the properties table and adds selection model and + * listener and adds a row sorter to the table model + */ + propsTable = new JTable(getTableModel()); + propsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + PropsListSelectionListener selectionListener = + new PropsListSelectionListener(); + propsTable.getSelectionModel().addListSelectionListener( + selectionListener); + propsTable.getColumnModel().getSelectionModel() + .addListSelectionListener(selectionListener); + TableRowSorter sorter = + new TableRowSorter(propsTable.getModel()); + propsTable.setRowSorter(sorter); + + JScrollPane scrollPane = new JScrollPane(propsTable); + + SearchField searchField = new SearchField("", sorter); + buttonsPanel = new ButtonsPanel(propsTable, searchField); + + centerPanel = new TransparentPanel(new BorderLayout()); + centerPanel.add(scrollPane, BorderLayout.CENTER); + centerPanel.add(buttonsPanel, BorderLayout.EAST); + + JLabel needRestart = + new JLabel( + resourceManagementService + .getI18NString("plugin.propertieseditor.NEED_RESTART")); + needRestart.setForeground(Color.RED); + + TransparentPanel searchPanel = + new TransparentPanel(new BorderLayout(5, 0)); + searchPanel.setBorder(BorderFactory.createEmptyBorder(3, 5, 3, 5)); + searchPanel.add(searchField, BorderLayout.CENTER); + + add(searchPanel, BorderLayout.NORTH); + add(centerPanel, BorderLayout.CENTER); + add(needRestart, BorderLayout.SOUTH); + } + + /** + * The table model of the props table. + */ + private PropsTableModel tableModel; + + /** + * Returns the table model of the props table. + * + * @return The PropsTableModel of the props table. + */ + private PropsTableModel getTableModel() + { + if (tableModel == null) + tableModel = new PropsTableModel(); + return tableModel; + } + + /** + * Listens for events triggered when a selection is made in the props list. + */ + private class PropsListSelectionListener + implements ListSelectionListener + { + + public void valueChanged(ListSelectionEvent e) + { + int selectedRow = propsTable.getSelectedRow(); + + if (selectedRow == -1) + { + buttonsPanel.defaultButtonState(); + return; + } + + buttonsPanel.enableDeleteButton(true); + } + } +} diff --git a/src/net/java/sip/communicator/plugin/propertieseditor/PropsTableModel.java b/src/net/java/sip/communicator/plugin/propertieseditor/PropsTableModel.java new file mode 100644 index 000000000..cc0e4036d --- /dev/null +++ b/src/net/java/sip/communicator/plugin/propertieseditor/PropsTableModel.java @@ -0,0 +1,139 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.plugin.propertieseditor; + +import java.beans.*; + +import javax.swing.event.*; +import javax.swing.table.*; +import org.jitsi.service.configuration.*; + +/** + * @author Marin Dzhigarov + * @author Pawel Domas + * + */ +public class PropsTableModel + implements TableModel, + PropertyChangeListener +{ + + /** + * The configuration service. + */ + private ConfigurationService confService = PropertiesEditorActivator.getConfigurationService(); + + /** + * Creates an instance of PropsTableModel. + */ + PropsTableModel() {} + + public void Register() + { + confService.addPropertyChangeListener(this); + } + public void Unregister() + { + confService.removePropertyChangeListener(this); + } + + public void propertyChange(PropertyChangeEvent evt) + { + for (TableModelListener l : listeners.getListeners(TableModelListener.class)) + { + l.tableChanged(new TableModelEvent(this)); + } + } + + public int getRowCount() + { + return confService.getAllPropertyNames().size(); + } + + /** + * Returns the count of table columns. + * @return int the count of table columns + */ + public int getColumnCount() + { + return 2; + } + + /** + * Returns the column name given column index. + * @param columnIndex The column index. + * @return The column name. + */ + public String getColumnName(int columnIndex) + { + if(columnIndex == 0) + { + return "Property"; + } else + { + return "Value"; + } + } + + /** + * Returns the class of the column given a column index + */ + public Class getColumnClass(int columnIndex) + { + return String.class; + } + + /** + * Returns true if the given cell is edittable. + * Edittable cells in this model are cells with column index 1. + * @param rowIndex The row index. + * @param columnIndex The column index. + * @return True if the column index is 1 + */ + public boolean isCellEditable(int rowIndex, int columnIndex) + { + return columnIndex == 1; + } + + /** + * Returns the value in the cell given by row and column. + */ + public Object getValueAt(int rowIndex, int columnIndex) + { + if (columnIndex == 0) + { + return confService.getAllPropertyNames().get(rowIndex); + } else + { + return confService.getProperty(confService.getAllPropertyNames().get(rowIndex)); + } + } + + /** + * Sets aValue at a cell with coordinates [rowIndex, columnIndex] + * @param aValue The given value. + * @param rowIndex The row index that the value will be set to. + * @param columnIndex The column index that the value will be set to. + */ + public void setValueAt(Object aValue, int rowIndex, int columnIndex) + { + String property = confService.getAllPropertyNames().get(rowIndex); + confService.setProperty(property, aValue); + } + + private EventListenerList listeners = new EventListenerList(); + + public void addTableModelListener(TableModelListener l) + { + listeners.add(TableModelListener.class, l); + } + + public void removeTableModelListener(TableModelListener l) + { + listeners.remove(TableModelListener.class, l); + } +} \ No newline at end of file diff --git a/src/net/java/sip/communicator/plugin/propertieseditor/SearchField.java b/src/net/java/sip/communicator/plugin/propertieseditor/SearchField.java new file mode 100644 index 000000000..a79f29bbc --- /dev/null +++ b/src/net/java/sip/communicator/plugin/propertieseditor/SearchField.java @@ -0,0 +1,158 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. See terms of license at gnu.org. + */ +package net.java.sip.communicator.plugin.propertieseditor; + +import java.awt.*; +import java.awt.event.*; + +import javax.swing.*; +import javax.swing.event.*; +import javax.swing.table.*; + +import net.java.sip.communicator.plugin.desktoputil.*; +import net.java.sip.communicator.plugin.desktoputil.plaf.*; +import net.java.sip.communicator.util.*; +import net.java.sip.communicator.util.skin.*; + +/** + * The field used for searching in the properties table. + * + * @author Marin Dzhigarov + * + */ +public class SearchField + extends SIPCommTextField + implements Skinnable +{ + + /** + * Serial Version UID. + */ + private static final long serialVersionUID = 1L; + + /** + * Class id key used in UIDefaults. + */ + private static final String uiClassID = SearchField.class.getName() + + "FieldUI"; + + /** + * The object used for logging. + */ + private Logger logger = Logger.getLogger(SearchField.class); + + TableRowSorter sorter; + + /** + * Adds the ui class to UIDefaults. + */ + static + { + UIManager.getDefaults().put(uiClassID, + SearchFieldUI.class.getName()); + } + + /** + * Creates an instance SearchField. + * + * @param text the text we would like to enter by default + * @param sorter the sorter which will be used for filtering. + */ + public SearchField(String text, final TableRowSorter sorter) + { + super(text); + + if (getUI() instanceof SearchFieldUI) + { + ((SearchFieldUI) getUI()).setDeleteButtonEnabled(true); + ((SearchFieldUI) getUI()).setCallButtonEnabled(false); + } + + this.setBorder(null); + this.setOpaque(false); + this.setPreferredSize(new Dimension(100, 25)); + this.setDragEnabled(true); + + InputMap imap = + getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + imap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "escape"); + ActionMap amap = getActionMap(); + amap.put("escape", new AbstractAction() + { + /** + * Serial Version UID. + */ + private static final long serialVersionUID = 1L; + + public void actionPerformed(ActionEvent e) + { + setText(""); + } + }); + + getDocument().addDocumentListener(new DocumentListener() + { + public void insertUpdate(DocumentEvent e) + { + RowFilter rf = null; + try + { + rf = RowFilter.regexFilter(getText(), 0); + } + catch (java.util.regex.PatternSyntaxException exception) + { + logger.info("Failed to compile regex.", exception); + return; + } + sorter.setRowFilter(rf); + } + + public void removeUpdate(DocumentEvent e) + { + RowFilter rf = null; + try + { + rf = RowFilter.regexFilter(getText(), 0); + } + catch (java.util.regex.PatternSyntaxException exception) + { + logger.info("Failed to compile regex.", exception); + return; + } + sorter.setRowFilter(rf); + } + + public void changedUpdate(DocumentEvent e) + { + } + }); + + loadSkin(); + } + + /** + * Returns the name of the L&F class that renders this component. + * + * @return the string "TreeUI" + * @see JComponent#getUIClassID + * @see UIDefaults#getUI + */ + public String getUIClassID() + { + return uiClassID; + } + + /** + * Reloads text field UI defs. + */ + public void loadSkin() + { + if (getUI() instanceof SearchFieldUI) + { + ((SearchFieldUI) getUI()).loadSkin(); + } + } +} diff --git a/src/net/java/sip/communicator/plugin/propertieseditor/StartingPanel.java b/src/net/java/sip/communicator/plugin/propertieseditor/StartingPanel.java new file mode 100644 index 000000000..5027dccea --- /dev/null +++ b/src/net/java/sip/communicator/plugin/propertieseditor/StartingPanel.java @@ -0,0 +1,60 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. See terms of license at gnu.org. + */ +package net.java.sip.communicator.plugin.propertieseditor; + +import java.awt.*; + +import net.java.sip.communicator.plugin.desktoputil.*; + +import org.jitsi.service.configuration.*; + +/** + * The StartingPanel wraps the WarningPanel and + * PropertiesEditorPanel. Its main purpose is to choose which one of + * the panels to set visible. + * + * @author Marin Dzhigarov + */ +public class StartingPanel + extends TransparentPanel +{ + /** + * Serial Version UID. + */ + private static final long serialVersionUID = 1L; + + private ConfigurationService confService = PropertiesEditorActivator + .getConfigurationService(); + + /* + * The WarningPanel + */ + WarningPanel warningPanel = new WarningPanel(this); + + /** + * The PropertiesEditorPanel + */ + PropertiesEditorPanel propertiesEditorPanel = new PropertiesEditorPanel(); + + /** + * Creates an instance StartingPanel + */ + public StartingPanel() + { + super(new BorderLayout()); + boolean showWarning = + confService.getBoolean(Constants.SHOW_WARNING_MSG_PROP, true); + + if (showWarning) + { + add(warningPanel, BorderLayout.CENTER); + } + else + { + add(propertiesEditorPanel, BorderLayout.CENTER); + } + } +} diff --git a/src/net/java/sip/communicator/plugin/propertieseditor/WarningPanel.java b/src/net/java/sip/communicator/plugin/propertieseditor/WarningPanel.java new file mode 100644 index 000000000..bf126df12 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/propertieseditor/WarningPanel.java @@ -0,0 +1,98 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. See terms of license at gnu.org. + */ +package net.java.sip.communicator.plugin.propertieseditor; + +import java.awt.*; +import java.awt.event.*; + +import javax.swing.*; + +import net.java.sip.communicator.plugin.desktoputil.*; + +import org.jitsi.service.configuration.*; +import org.jitsi.service.resources.*; + +/** + * The WarningPanel allows users to change Jitsi configuration + * properties at runtime. It wraps the PropertiesEditorPanel in order + * to provide some more explanations and make complex configurations available + * only to advanced users. + * + * @author Marin Dzhigarov + */ +public class WarningPanel + extends TransparentPanel +{ + /** + * Serial version UID. + */ + private static final long serialVersionUID = 1L; + + private ResourceManagementService resourceManagementService = + PropertiesEditorActivator.getResourceManagementService(); + + private ConfigurationService confService = PropertiesEditorActivator + .getConfigurationService(); + + private JCheckBox checkBox; + + /** + * Creates an instance WarningPanel + * + * @param startingPanel + */ + public WarningPanel(final StartingPanel startingPanel) + { + super(new BorderLayout()); + + this.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); + + JPanel mainPanel = new TransparentPanel(new BorderLayout(0, 10)); + add(mainPanel, BorderLayout.NORTH); + + JTextPane warningMsg = new JTextPane(); + warningMsg.setEditable(false); + warningMsg.setOpaque(false); + warningMsg.setText(resourceManagementService + .getI18NString("plugin.propertieseditor.DESCRIPTION")); + + checkBox = + new JCheckBox( + resourceManagementService + .getI18NString("plugin.propertieseditor.CHECK_BOX")); + checkBox.setOpaque(false); + checkBox.setSelected(true); + + mainPanel.add(warningMsg, BorderLayout.NORTH); + mainPanel.add(checkBox, BorderLayout.CENTER); + + JButton btn = + new JButton( + resourceManagementService + .getI18NString("plugin.propertieseditor.IM_AWARE")); + btn.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + confService.setProperty(Constants.SHOW_WARNING_MSG_PROP, + new Boolean(checkBox.isSelected())); + + startingPanel.removeAll(); + startingPanel.add(startingPanel.propertiesEditorPanel, + BorderLayout.CENTER); + startingPanel.propertiesEditorPanel.setVisible(true); + startingPanel.revalidate(); + startingPanel.repaint(); + } + }); + + JPanel buttonPanel = + new TransparentPanel(new FlowLayout(FlowLayout.CENTER)); + buttonPanel.add(btn); + + mainPanel.add(buttonPanel, BorderLayout.SOUTH); + } +} diff --git a/src/net/java/sip/communicator/plugin/propertieseditor/propertieseditor.manifest.mf b/src/net/java/sip/communicator/plugin/propertieseditor/propertieseditor.manifest.mf new file mode 100644 index 000000000..10f68c24d --- /dev/null +++ b/src/net/java/sip/communicator/plugin/propertieseditor/propertieseditor.manifest.mf @@ -0,0 +1,22 @@ +Bundle-Activator: net.java.sip.communicator.plugin.propertieseditor.PropertiesEditorActivator +Bundle-Description: A panel that allows users to configure properties +Bundle-Vendor: jitsi.org +Bundle-Version: 0.0.1 +System-Bundle: yes +Import-Package: org.osgi.framework, + org.jitsi.service.configuration, + org.jitsi.service.resources, + net.java.sip.communicator.service.resources, + net.java.sip.communicator.service.gui, + net.java.sip.communicator.service.gui.event, + net.java.sip.communicator.util, + net.java.sip.communicator.util.skin, + net.java.sip.communicator.plugin.desktoputil, + net.java.sip.communicator.plugin.desktoputil.event, + net.java.sip.communicator.plugin.desktoputil.plaf, + javax.swing, + javax.swing.event, + javax.swing.table, + javax.swing.text, + javax.swing.border, + javax.swing.plaf diff --git a/src/net/java/sip/communicator/util/UtilActivator.java b/src/net/java/sip/communicator/util/UtilActivator.java index 449b171ac..7c3b43e17 100644 --- a/src/net/java/sip/communicator/util/UtilActivator.java +++ b/src/net/java/sip/communicator/util/UtilActivator.java @@ -6,7 +6,6 @@ */ package net.java.sip.communicator.util; -//import java.awt.image.*; import java.util.*; import net.java.sip.communicator.service.gui.*;