Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.

Close

ToolbarTools Class Refactoring

Emilio
2011-11-07
2012-10-07
  • Emilio
    Emilio
    2011-11-07

    I did some modifications to the class ToolbarTools, so that it avoids code
    repetition and makes the process of adding a button more automatic and less
    error prone. I documented it with JavaDoc. I tested it and it works well. It
    respects all other classes.

    For it to work I created a new class ToolButton.

    MODIFIED TOOLBARTOOLS CLASS

    package toolbars;
    
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.event.*;
    import java.util.*;
    import java.net.*;
    
    import globals.*;
    import circuit.*;
    
    /**
     ToolbarTools class
    
     @author Davide Bucci & Jose Emilio Munoz
    
     <pre>
     This file is part of FidoCadJ.
    
     FidoCadJ is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation, either version 3 of the License, or
     (at your option) any later version.
    
     FidoCadJ 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 General Public License for more details.
    
     You should have received a copy of the GNU General Public License
     along with FidoCadJ.  If not, see <[url]http://www.gnu.org/licenses/[/url]>.
    
     Copyright 2008-2011 by Davide Bucci
     </pre>
    
     This class allows to add and organise the buttons in the toolbar. Buttons are instances of <code>JToggleButton</code>, 
     i.e. they have two states, selected and not selected. To make it easier to add a button, they are defined
     first as a <code>ToolButton</code> ({@link ToolButton}), then they are assigned their variable name,
     and they are finally added to the toolbar using the appropiate method ({@link #addToolButton(JToggleButton, int)}).</p> 
     Once they are added to the toolbar, their action when selected must be defined. They each implement their 
     own <code>ActionListener</code> (inner classes) and <code>actionPerformed</code> methods so that they can each have a 
     different behavior if required.</p> 
     When created they are automatically added to an <code>ArrayList</code> (to loop through this list and find the selected button, 
     {@link #getSelectedButton()}, this is used in {@link #getSelectionState()}), to a <code>HashMap</code> (to assign and find 
     the <code>CircuitPanel</code> constant of each button, this is used in {@link #setSelectionState(int, String)}) and to a 
     <code>ButtonGroup</code>, so that only one button is selected at a time.</p>
    
     */
    
    public class ToolbarTools extends JToolBar implements ChangeSelectionListener
    
    {
        private ChangeSelectionListener selectionListener;
    
        //Instance variable of each button
        private JToggleButton selection;
        private JToggleButton zoom;
        private JToggleButton hand;  
        private JToggleButton line;
        private JToggleButton advtext;
        private JToggleButton bezier;
        private JToggleButton polygon;
        private JToggleButton ellipse;
        private JToggleButton rectangle;
        private JToggleButton connection;    
        private JToggleButton pcbline;
        private JToggleButton pcbpad;
    
        private static String base;
        private static boolean showText;
    
        private ButtonGroup group;
        private ArrayList<JToggleButton> toolButtonsList;
        private HashMap<JToggleButton,Integer> circuitPanelConstants;
    
        /** <code>base</code> is passed to the <code>ToolbarTools</code> constructor to create the toolbar,
          but will need to be accessed by the <code>ToolButton</code> class to create each button.
    
          @return base    
          */
    
        public static String getBase() {
            return base;
        }
    
        /** <code>showText</code> is passed to the <code>ToolbarTools</code> constructor to create the toolbar,
          but will need to be accessed by the <code>ToolButton</code> class to create each button.
    
          @return showText
          */
    
        public static boolean getShowText() {
            return showText;
        }
    
        /** This method effectively adds the defined button to the toolbar.
          * 
          @param button - Name of the button to be added to the toolbar.
          @param circuitPanelConstant - Determines its function, see <code>circuitPanel</code> class.
          */
    
        public void addToolButton(JToggleButton button, int circuitPanelConstant) {
            add(button);
            group.add(button);
            toolButtonsList.add(button);
            circuitPanelConstants.put(button, circuitPanelConstant);
        }
    
        /** Class Constructor 
          Creates the toolbar, consisting of all the buttons, which are displayed
          from left to right, in the order they were added.
    
          @param showText - True if the name of the tool is to be displayed underneath the icon.
          @param smallIcons - True if 16x16 size icons are to be displayed.
          */
    
        public ToolbarTools (boolean showText, boolean smallIcons) {
    
            base = smallIcons ? "icons16/" : "icons32/";
            this.showText = showText;
    
            putClientProperty("Quaqua.ToolBar.style", "title");
    
            setBorderPainted(false);
    
            group = new ButtonGroup();
            toolButtonsList = new ArrayList<JToggleButton>();
            circuitPanelConstants = new HashMap<JToggleButton,Integer>();
    
            /**
             * First button to be added. Firstly a ToolButton object is created by
             * defining an icon image, the text displaying the name of the tool,
             * the button ActionCommand, and the tool description/tip. Then it is
             * assigned to the appropriate instance variable using the
             * ToolButton.getToolButton() method. Finally button behavior is
             * defined. As the button circuitPanel constant was already defined
             * when adding the button, the appropriate constant is now fetched from
             * the circuitPanelConstants HashMap.
             * */
            ToolButton selectionToolButton = new ToolButton("arrow.png", "Selection", "selection", "tooltip_selection");
            selection = selectionToolButton.getToolButton();
            addToolButton(selection, CircuitPanel.SELECTION);
    
            selection.addActionListener(new ActionListener() {                                                         
                public void actionPerformed(ActionEvent ev)               
                {                                                        
                    selectionListener.setSelectionState(circuitPanelConstants.get(selection),"");
                }                                                        
            });   
            /** End of button definition. */
    
            ToolButton zoomToolButton = new ToolButton("magnifier.png", "Zoom_p", "zoom", "tooltip_zoom");
            zoom = zoomToolButton.getToolButton();
            addToolButton(zoom, CircuitPanel.ZOOM);
    
            zoom.addActionListener(new ActionListener() {                                                         
                public void actionPerformed(ActionEvent ev)               
                {                                                        
                    selectionListener.setSelectionState(circuitPanelConstants.get(zoom),"");
                }                                                        
            });
    
            ToolButton handToolButton = new ToolButton("move.png", "Hand", "hand", "tooltip_hand");
            hand = handToolButton.getToolButton();
            addToolButton(hand, CircuitPanel.HAND);
    
            hand.addActionListener(new ActionListener() {                                                         
                public void actionPerformed(ActionEvent ev)               
                {                                                        
                    selectionListener.setSelectionState(circuitPanelConstants.get(hand),"");
                }                                                        
            });
    
            ToolButton lineToolButton = new ToolButton("line.png", "Line", "line", "tooltip_line");
            line = lineToolButton.getToolButton();
            addToolButton(line, CircuitPanel.LINE);
    
            line.addActionListener(new ActionListener() {                                                         
                public void actionPerformed(ActionEvent ev)               
                {                                                        
                    selectionListener.setSelectionState(circuitPanelConstants.get(line),"");
                }                                                        
            });
    
            ToolButton advtextToolButton = new ToolButton("text.png", "Text", "text", "tooltip_text");
            advtext = advtextToolButton.getToolButton();
            addToolButton(advtext, CircuitPanel.TEXT);
    
            advtext.addActionListener(new ActionListener() {                                                         
                public void actionPerformed(ActionEvent ev)               
                {                                                        
                    selectionListener.setSelectionState(circuitPanelConstants.get(advtext),"");
                }                                                        
            });
    
            ToolButton bezierToolButton = new ToolButton("bezier.png", "Bezier", "bezier", "tooltip_bezier");
            bezier = bezierToolButton.getToolButton();
            addToolButton(bezier, CircuitPanel.BEZIER);
    
            bezier.addActionListener(new ActionListener() {                                                         
                public void actionPerformed(ActionEvent ev)               
                {                                                        
                    selectionListener.setSelectionState(circuitPanelConstants.get(bezier),"");
                }                                                        
            });
    
            ToolButton polygonToolButton = new ToolButton("polygon.png", "Polygon", "polygon", "tooltip_polygon");
            polygon = polygonToolButton.getToolButton();
            addToolButton(polygon, CircuitPanel.POLYGON);
    
            polygon.addActionListener(new ActionListener() {                                                         
                public void actionPerformed(ActionEvent ev)               
                {                                                        
                    selectionListener.setSelectionState(circuitPanelConstants.get(polygon),"");
                }                                                        
            });
    
            ToolButton ellipseToolButton = new ToolButton("ellipse.png", "Ellipse", "ellipse", "tooltip_ellipse");
            ellipse = ellipseToolButton.getToolButton();
            addToolButton(ellipse, CircuitPanel.ELLIPSE);
    
            ellipse.addActionListener(new ActionListener() {                                                         
                public void actionPerformed(ActionEvent ev)               
                {                                                        
                    selectionListener.setSelectionState(circuitPanelConstants.get(ellipse),"");
                }                                                        
            });
    
            ToolButton rectangleToolButton = new ToolButton("rectangle.png", "Rectangle", "rectangle", "tooltip_rectangle");
            rectangle = rectangleToolButton.getToolButton();
            addToolButton(rectangle, CircuitPanel.RECTANGLE);
    
            rectangle.addActionListener(new ActionListener() {                                                         
                public void actionPerformed(ActionEvent ev)               
                {                                                        
                    selectionListener.setSelectionState(circuitPanelConstants.get(rectangle),"");
                }                                                        
            });
    
            ToolButton connectionToolButton = new ToolButton("connection.png", "Connection", "connection", "tooltip_connection");
            connection = connectionToolButton.getToolButton();
            addToolButton(connection, CircuitPanel.CONNECTION);
    
            connection.addActionListener(new ActionListener() {                                                         
                public void actionPerformed(ActionEvent ev)               
                {                                                        
                    selectionListener.setSelectionState(circuitPanelConstants.get(connection),"");
                }                                                        
            });
    
            ToolButton pcblineToolButton = new ToolButton("pcbline.png", "PCBline", "pcbline", "tooltip_pcbline");
            pcbline = pcblineToolButton.getToolButton();
            addToolButton(pcbline, CircuitPanel.PCB_LINE);
    
            pcbline.addActionListener(new ActionListener() {                                                         
                public void actionPerformed(ActionEvent ev)               
                {                                                        
                    selectionListener.setSelectionState(circuitPanelConstants.get(pcbline),"");
                }                                                        
            });
    
            ToolButton pcbpadToolButton = new ToolButton("pcbpad.png", "PCBpad", "pcbpad", "tooltip_pcbpad");
            pcbpad = pcbpadToolButton.getToolButton();
            addToolButton(pcbpad, CircuitPanel.PCB_PAD);
    
            pcbpad.addActionListener(new ActionListener() {                                                         
                public void actionPerformed(ActionEvent ev)               
                {                                                        
                    selectionListener.setSelectionState(circuitPanelConstants.get(pcbpad),"");
                }                                                        
            });
    
            add(Box.createGlue());
    
            setFloatable(false);
            setRollover(true);
    
        }
    
        /** Add a selection listener (object implementing the ChangeSelection 
          interface) whose change method will be called when the current
          selected action should be changed.
    
          */
    
        public void addSelectionListener(ChangeSelectionListener c)
        {
            selectionListener=c;
        }
    
        /** This method finds the button selected at the moment.
          * 
          @return selectedButton
          */
    
        public JToggleButton getSelectedButton(){
            JToggleButton selectedButton = null;
            for (JToggleButton button : toolButtonsList) {
                if (button.isSelected()) {
                    selectedButton = button;
                }
            }
            return selectedButton;
        }
    
        /** Get the current selection state. Required for implementing the
          ChangeSelectionListener interface.
    
          @return the actual selection state (see the CircuitPanel class for the
          definition of the constants used here).
          */
    
        public int getSelectionState()
        {
            JToggleButton selectedButton = getSelectedButton();
            if(!selectedButton.equals(null)) {
                return circuitPanelConstants.get(selectedButton);
            }
            else {
                return CircuitPanel.NONE;
            }
        }
    
        /** Set the current selection state. Required for implementing the
          ChangeSelectionListener interface
    
          @param s the selection state (see the CircuitPanel class for the
          definition of the constants used here).
          @param m not used here (useful when playing with macros).
          */
    
        public void setSelectionState(int s, String m)
        {
            for (JToggleButton button : toolButtonsList) {
                button.setSelected(false);
            }
    
            for(JToggleButton button : circuitPanelConstants.keySet()){
                if(s == CircuitPanel.NONE || s == CircuitPanel.MACRO) break;
                if(circuitPanelConstants.get(button).equals(s)) button.setSelected(true);
            }
        }
    }
    

    NEW TOOLBUTTON CLASS

    package toolbars;
    
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.event.*;
    import java.util.*;
    import java.net.*;
    
    import globals.*;
    import circuit.*;
    
    /**
     ToolButton class
    
     @author Davide Bucci & Jose Emilio Munoz
    
     <pre>
     This file is part of FidoCadJ.
    
     FidoCadJ is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation, either version 3 of the License, or
     (at your option) any later version.
    
     FidoCadJ 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 General Public License for more details.
    
     You should have received a copy of the GNU General Public License
     along with FidoCadJ.  If not, see <[url]http://www.gnu.org/licenses/[/url]>.
    
     Copyright 2008-2011 by Davide Bucci
     </pre>
    
     This class contains a constructor, which allows to create buttons for the FidoCadJ toolbar, {@link ToolbarTools}.
     Having the button created in this class allows to add a button in the <code>ToolbarTools</code> class by defining most of
     the button parameters on a single line. This also avoids code repetition and gives more flexibility to design the buttons.
    
     */
    
    public class ToolButton {
    
        private JToggleButton toolButton;
    
        /** Class Constructor: Creates a new <code>JToggleButton</code> that has the specified text and image, 
          and that is initially unselected. It also assigns an <code>actionCommand</code> and a <code>toolTip</code> 
          to the button.
    
          @param image - Icon image file. 
          @param toolText - Button text, a <code>Globals</code> message.
          @param actionCommand - Button action command.
          @param toolTip - Button description/tip, a <code>Globals</code> message.
          */
    
        public ToolButton (String image, String toolText, String actionCommand, String toolTip) {
    
            String base = ToolbarTools.getBase();
            boolean showText = ToolbarTools.getShowText();
    
            URL url = ToolbarTools.class.getResource(base+image);
    
            toolButton = new JToggleButton(
                                           (showText?Globals.messages.getString(toolText):""),
                                           new ImageIcon(url));
            toolButton.setActionCommand(actionCommand);
            toolButton.setToolTipText(
                                      Globals.messages.getString(toolTip));
    
            toolButton.setVerticalTextPosition(SwingConstants.BOTTOM);
            toolButton.setHorizontalTextPosition(SwingConstants.CENTER);
    
            toolButton.putClientProperty("Quaqua.Button.style","toolBarTab");
    
        }
    
        /** With this method, the button can be passed to the <code>ToolbarTools</code> class as a
          <code>JToggleButton</code>.
    
          @return toolButton
          */
    
        public JToggleButton getToolButton() {
    
            return toolButton;
    
        }
    
    }
    

    I welcome feedback and help to refactor this class successfully.
    Thank you very much.

    Emilio

     
  • Davide Bucci
    Davide Bucci
    2011-11-07

    Dear Emilio,
    thanks for your contribution. I am very happy to hear that someone is willing
    to contribute effectively to FidoCadJ.
    Your code seems OK to me, but can you please reformat it to comply to the
    coding style rules described in the README, paragraph 3.4?

    3.4 Coding conventions
    ----------------------
    
    The following coding conventions have been applied for the FidoCadJ source 
    code:
    
    - tab set to 4 spaces
    - blocks delimited by curly braces are indented as follows:
    
        for(i=0; i<10; ++i) {   // starting brace here
            // indented code (4 spaces)
            System.out.println("I counted up to "+i);
        }   // close brace here at the same level of the 'if'
    
    - methods are indented as follows:
    
        void dummy (int i, int j) 
        {   // put the starting brace here
            System.out.println("Indent code");
        }   // put the closing brace here
    
    - the class names always start with a capital letter, and so does methods
    - variables never start with a capital letter
    - an instance of the class does have its first letter in lower case
    - each public class and method should be documented with Javadoc syntax
    - no lines longer than 80 characters
    - commits should not break the build
    

    In particular, I see that you tend to use lines longer than 80 characters and
    you put the opening curly brace of a method in a way it is not coherent with
    the current coding style. Of course, this is just a matter of taste, but it is
    important that the coding style remains coherent through all the project. The
    use of 4 space tabs is also quite important.

    If you can reformat your code according to the rules given in the README, I
    will be very happy to give you write acces to the source code repository and
    you will commit your changes. In a second time, if you want to continue to
    refactor other classes (this is a very good thing, and I try to do that on a
    regular basis), you might first post a topic on this forum, describing what
    you want to refactor and why. This will be useful to organize the coding
    activity and minimize the chance of conflicts.

    Remember that a commit should not break the build, i.e. the result of a commit
    should always compile fine.

    Regards,

    D.

     
  • Emilio
    Emilio
    2011-11-07

    Dear Davide,

    I followed your suggestions and reformatted the code. Please let me know if I
    need to change anything else. Thank you very much for your help and support.

    Yours sincerely,
    Emilio

    MODIFIED TOOLBARTOOLS CLASS

    package toolbars;
    
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.event.*;
    import java.util.*;
    import java.net.*;
    
    import globals.*;
    import circuit.*;
    
    /**
     ToolbarTools class
    
     @author Davide Bucci & Jose Emilio Munoz
    
     <pre>
     This file is part of FidoCadJ.
    
     FidoCadJ is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation, either version 3 of the License, or
     (at your option) any later version.
    
     FidoCadJ 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 General Public License for more details.
    
     You should have received a copy of the GNU General Public License
     along with FidoCadJ.  If not, see <[url]http://www.gnu.org/licenses/[/url]>.
    
     Copyright 2008-2011 by Davide Bucci
     </pre>
    
     This class allows to add and organise the buttons in the toolbar. Buttons are 
     instances of <code>JToggleButton</code>, i.e. they have two states, selected 
     and not selected. To make it easier to add a button, they are defined first 
     as a <code>ToolButton</code> ({@link ToolButton}), then they are assigned 
     their variable name, and they are finally added to the toolbar using the 
     appropiate method ({@link #addToolButton(JToggleButton, int)}).</p> 
     Once they are added to the toolbar, their action when selected must be 
     defined. They each implement their own <code>ActionListener</code> (inner 
     classes) and <code>actionPerformed</code> methods so that they can each have 
     a different behavior if required.</p> 
     When created they are automatically added to an <code>ArrayList</code> (to 
     loop through this list and find the selected button,
     {@link #getSelectedButton()}, this is used in {@link #getSelectionState()}), 
     to a <code>HashMap</code> (to assign and find the <code>CircuitPanel</code> 
     constant of each button, this is used in 
     {@link #setSelectionState(int, String)}) and to a <code>ButtonGroup</code>, 
     so that only one button is selected at a time.</p>
    
     */
    
    public class ToolbarTools extends JToolBar implements ChangeSelectionListener
    
    {
        private ChangeSelectionListener selectionListener;
    
        //Instance variable of each button
        private JToggleButton selection;
        private JToggleButton zoom;
        private JToggleButton hand;  
        private JToggleButton line;
        private JToggleButton advtext;
        private JToggleButton bezier;
        private JToggleButton polygon;
        private JToggleButton ellipse;
        private JToggleButton rectangle;
        private JToggleButton connection;    
        private JToggleButton pcbline;
        private JToggleButton pcbpad;
    
        private static String base;
        private static boolean showText;
    
        private ButtonGroup group;
        private ArrayList<JToggleButton> toolButtonsList;
        private HashMap<JToggleButton,Integer> circuitPanelConstants;
    
        /** <code>base</code> is passed to the <code>ToolbarTools</code> 
         constructor to create the toolbar, but will need to be accessed by the 
         <code>ToolButton</code> class to create each button.
    
         @return base    
         */
    
        public static String getBase() 
        {
            return base;
        }
    
        /** <code>showText</code> is passed to the <code>ToolbarTools</code> 
         constructor to create the toolbar, but will need to be accessed by the 
         <code>ToolButton</code> class to create each button.
    
         @return showText
         */
    
        public static boolean getShowText() 
        {
            return showText;
        }
    
        /** This method effectively adds the defined button to the toolbar.
    
         @param button - Name of the button to be added to the toolbar.
         @param circuitPanelConstant - Determines its function, see 
         <code>circuitPanel</code> class.
         */
    
        public void addToolButton(JToggleButton button, int circuitPanelConstant) 
        {
            add(button);
            group.add(button);
            toolButtonsList.add(button);
            circuitPanelConstants.put(button, circuitPanelConstant);
        }
    
        /** Class Constructor 
         Creates the toolbar, consisting of all the buttons, which are displayed
         from left to right, in the order they were added.
    
         @param showText - True if the name of the tool is to be displayed 
         underneath the icon.
         @param smallIcons - True if 16x16 size icons are to be displayed.
         */
    
        public ToolbarTools (boolean showText, boolean smallIcons) 
        {
    
            base = smallIcons ? "icons16/" : "icons32/";
            this.showText = showText;
    
            putClientProperty("Quaqua.ToolBar.style", "title");
    
            setBorderPainted(false);
    
            group = new ButtonGroup();
            toolButtonsList = new ArrayList<JToggleButton>();
            circuitPanelConstants = new HashMap<JToggleButton,Integer>();
    
            /**
             * First button to be added. Firstly a ToolButton object is created by
             * defining an icon image, the text displaying the name of the tool,
             * the button ActionCommand, and the tool description/tip. Then it is
             * assigned to the appropriate instance variable using the
             * ToolButton.getToolButton() method. Finally button behavior is
             * defined. As the button circuitPanel constant was already defined
             * when adding the button, the appropriate constant is now fetched from
             * the circuitPanelConstants HashMap.
             * */
    
            ToolButton selectionToolButton = new ToolButton("arrow.png", 
                                                            "Selection", 
                                                            "selection", 
                                                            "tooltip_selection");
            selection = selectionToolButton.getToolButton();
            addToolButton(selection, CircuitPanel.SELECTION);
    
            selection.addActionListener(new ActionListener() {                                                         
                public void actionPerformed(ActionEvent ev)               
                {                                                        
                    selectionListener.
                    setSelectionState(circuitPanelConstants.get(selection),"");
                }                                                        
            });   
            /** End of button definition. */
    
            ToolButton zoomToolButton = new ToolButton("magnifier.png", 
                                                       "Zoom_p", 
                                                       "zoom", 
                                                       "tooltip_zoom");
            zoom = zoomToolButton.getToolButton();
            addToolButton(zoom, CircuitPanel.ZOOM);
    
            zoom.addActionListener(new ActionListener() {                                                         
                public void actionPerformed(ActionEvent ev)               
                {                                                        
                    selectionListener.
                    setSelectionState(circuitPanelConstants.get(zoom),"");
                }                                                        
            });
    
            ToolButton handToolButton = new ToolButton("move.png", 
                                                       "Hand", 
                                                       "hand", 
                                                       "tooltip_hand");
            hand = handToolButton.getToolButton();
            addToolButton(hand, CircuitPanel.HAND);
    
            hand.addActionListener(new ActionListener() {                                                         
                public void actionPerformed(ActionEvent ev)               
                {                                                        
                    selectionListener.
                    setSelectionState(circuitPanelConstants.get(hand),"");
                }                                                        
            });
    
            ToolButton lineToolButton = new ToolButton("line.png", 
                                                       "Line", 
                                                       "line", 
                                                       "tooltip_line");
            line = lineToolButton.getToolButton();
            addToolButton(line, CircuitPanel.LINE);
    
            line.addActionListener(new ActionListener() {                                                         
                public void actionPerformed(ActionEvent ev)               
                {                                                        
                    selectionListener.
                    setSelectionState(circuitPanelConstants.get(line),"");
                }                                                        
            });
    
            ToolButton advtextToolButton = new ToolButton("text.png", 
                                                          "Text", 
                                                          "text", 
                                                          "tooltip_text");
            advtext = advtextToolButton.getToolButton();
            addToolButton(advtext, CircuitPanel.TEXT);
    
            advtext.addActionListener(new ActionListener() {                                                         
                public void actionPerformed(ActionEvent ev)               
                {                                                        
                    selectionListener.
                    setSelectionState(circuitPanelConstants.get(advtext),"");
                }                                                        
            });
    
            ToolButton bezierToolButton = new ToolButton("bezier.png", 
                                                         "Bezier", 
                                                         "bezier", 
                                                         "tooltip_bezier");
            bezier = bezierToolButton.getToolButton();
            addToolButton(bezier, CircuitPanel.BEZIER);
    
            bezier.addActionListener(new ActionListener() {                                                         
                public void actionPerformed(ActionEvent ev)               
                {                                                        
                    selectionListener.
                    setSelectionState(circuitPanelConstants.get(bezier),"");
                }                                                        
            });
    
            ToolButton polygonToolButton = new ToolButton("polygon.png", 
                                                          "Polygon", 
                                                          "polygon", 
                                                          "tooltip_polygon");
            polygon = polygonToolButton.getToolButton();
            addToolButton(polygon, CircuitPanel.POLYGON);
    
            polygon.addActionListener(new ActionListener() {                                                         
                public void actionPerformed(ActionEvent ev)               
                {                                                        
                    selectionListener.
                    setSelectionState(circuitPanelConstants.get(polygon),"");
                }                                                        
            });
    
            ToolButton ellipseToolButton = new ToolButton("ellipse.png", 
                                                          "Ellipse", 
                                                          "ellipse", 
                                                          "tooltip_ellipse");
            ellipse = ellipseToolButton.getToolButton();
            addToolButton(ellipse, CircuitPanel.ELLIPSE);
    
            ellipse.addActionListener(new ActionListener() {                                                         
                public void actionPerformed(ActionEvent ev)               
                {                                                        
                    selectionListener.
                    setSelectionState(circuitPanelConstants.get(ellipse),"");
                }                                                        
            });
    
            ToolButton rectangleToolButton = new ToolButton("rectangle.png", 
                                                            "Rectangle", 
                                                            "rectangle", 
                                                            "tooltip_rectangle");
            rectangle = rectangleToolButton.getToolButton();
            addToolButton(rectangle, CircuitPanel.RECTANGLE);
    
            rectangle.addActionListener(new ActionListener() {                                                         
                public void actionPerformed(ActionEvent ev)               
                {                                                        
                    selectionListener.
                    setSelectionState(circuitPanelConstants.get(rectangle),"");
                }                                                        
            });
    
            ToolButton connectionToolButton = new ToolButton("connection.png", 
                                                             "Connection", 
                                                             "connection", 
                                                             "tooltip_connection");
            connection = connectionToolButton.getToolButton();
            addToolButton(connection, CircuitPanel.CONNECTION);
    
            connection.addActionListener(new ActionListener() {                                                         
                public void actionPerformed(ActionEvent ev)               
                {                                                        
                    selectionListener.
                    setSelectionState(circuitPanelConstants.get(connection),"");
                }                                                        
            });
    
            ToolButton pcblineToolButton = new ToolButton("pcbline.png", 
                                                          "PCBline", 
                                                          "pcbline", 
                                                          "tooltip_pcbline");
            pcbline = pcblineToolButton.getToolButton();
            addToolButton(pcbline, CircuitPanel.PCB_LINE);
    
            pcbline.addActionListener(new ActionListener() {                                                         
                public void actionPerformed(ActionEvent ev)               
                {                                                        
                    selectionListener.
                    setSelectionState(circuitPanelConstants.get(pcbline),"");
                }                                                        
            });
    
            ToolButton pcbpadToolButton = new ToolButton("pcbpad.png", 
                                                         "PCBpad", 
                                                         "pcbpad", 
                                                         "tooltip_pcbpad");
            pcbpad = pcbpadToolButton.getToolButton();
            addToolButton(pcbpad, CircuitPanel.PCB_PAD);
    
            pcbpad.addActionListener(new ActionListener() {                                                         
                public void actionPerformed(ActionEvent ev)               
                {                                                        
                    selectionListener.
                    setSelectionState(circuitPanelConstants.get(pcbpad),"");
                }                                                        
            });
    
            add(Box.createGlue());
    
            setFloatable(false);
            setRollover(true);
    
        }
    
        /** Add a selection listener (object implementing the ChangeSelection 
         interface) whose change method will be called when the current
         selected action should be changed.
    
         */
    
        public void addSelectionListener(ChangeSelectionListener c)
        {
            selectionListener=c;
        }
    
        /** This method finds the button selected at the moment.
    
         @return selectedButton
         */
    
        public JToggleButton getSelectedButton()
        {
            JToggleButton selectedButton = null;
            for (JToggleButton button : toolButtonsList) {
                if (button.isSelected()) {
                    selectedButton = button;
                }
            }
            return selectedButton;
        }
    
        /** Get the current selection state. Required for implementing the
         ChangeSelectionListener interface.
    
         @return the actual selection state (see the CircuitPanel class for the
         definition of the constants used here).
         */
    
        public int getSelectionState()
        {
            JToggleButton selectedButton = getSelectedButton();
            if(!selectedButton.equals(null)) {
                return circuitPanelConstants.get(selectedButton);
            }
            else {
                return CircuitPanel.NONE;
            }
        }
    
        /** Set the current selection state. Required for implementing the
         ChangeSelectionListener interface
    
         @param s the selection state (see the CircuitPanel class for the
         definition of the constants used here).
         @param m not used here (useful when playing with macros).
         */
    
        public void setSelectionState(int s, String m)
        {
            for (JToggleButton button : toolButtonsList) {
                button.setSelected(false);
            }
    
            for(JToggleButton button : circuitPanelConstants.keySet()){
                if(s == CircuitPanel.NONE || s == CircuitPanel.MACRO) break;
                if(circuitPanelConstants.get(button).equals(s)) 
                    button.setSelected(true);
            }
        }
    }
    

    NEW TOOLBUTTON CLASS

    package toolbars;
    
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.event.*;
    import java.util.*;
    import java.net.*;
    
    import globals.*;
    import circuit.*;
    
    /**
     ToolButton class
    
     @author Davide Bucci & Jose Emilio Munoz
    
     <pre>
     This file is part of FidoCadJ.
    
     FidoCadJ is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation, either version 3 of the License, or
     (at your option) any later version.
    
     FidoCadJ 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 General Public License for more details.
    
     You should have received a copy of the GNU General Public License
     along with FidoCadJ.  If not, see <[url]http://www.gnu.org/licenses/[/url]>.
    
     Copyright 2008-2011 by Davide Bucci
     </pre>
    
     This class contains a constructor, which allows to create buttons for the 
     FidoCadJ toolbar, {@link ToolbarTools}.
     Having the button created in this class allows to add a button in the 
     <code>ToolbarTools</code> class by defining most of the button parameters on 
     a single line. This also avoids code repetition and gives more flexibility to 
     design the buttons.
    
     */
    
    public class ToolButton {
    
        private JToggleButton toolButton;
    
        /** Class Constructor: Creates a new <code>JToggleButton</code> that has 
         the specified text and image, and that is initially unselected. It also 
         assigns an <code>actionCommand</code> and a <code>toolTip</code> to the 
         button.
    
         @param image - Icon image file. 
         @param toolText - Button text, a <code>Globals</code> message.
         @param actionCommand - Button action command.
         @param toolTip - Button description/tip, a <code>Globals</code> message.
         */
    
        public ToolButton (String image, 
                           String toolText, 
                           String actionCommand, 
                           String toolTip) 
        {
    
            String base = ToolbarTools.getBase();
            boolean showText = ToolbarTools.getShowText();
    
            URL url = ToolbarTools.class.getResource(base+image);
    
            toolButton = new JToggleButton((showText?Globals.messages.
                                            getString(toolText):""),
                                           new ImageIcon(url));
    
            toolButton.setActionCommand(actionCommand);
    
            toolButton.setToolTipText(Globals.messages.getString(toolTip));
    
            toolButton.setVerticalTextPosition(SwingConstants.BOTTOM);
            toolButton.setHorizontalTextPosition(SwingConstants.CENTER);
    
            toolButton.putClientProperty("Quaqua.Button.style","toolBarTab");
    
        }
    
        /** With this method, the button can be passed to the 
         <code>ToolbarTools</code> class as a <code>JToggleButton</code>.
    
         @return toolButton
         */
    
        public JToggleButton getToolButton() 
        {
            return toolButton;
        }
    }
    
     
  • Davide Bucci
    Davide Bucci
    2011-11-08

    Dear Emilio,
    you now have a write access to the SVN source code repository.
    You can do a submit of your modifications and they will become part of the
    official codebase of FidoCadJ :-)
    If you would like to refactor other classes, I think it would be a good idea:
    there are several places where a little cleanup of the code can be useful.
    Once you decided what to do, you might open a new topic here on the forum to
    discuss about it. In a second time, when you will become acquainted with the
    internal structure of FidoCadJ, you might consider to add some new code of
    your own.

    Many thanks and regards,

    D.

     
  • Emilio
    Emilio
    2011-11-08

    Dear Davide,

    Thank you very much. However I do not know how to submit my modifications, or
    where shall I submit them. Shall I submit the .java files or the .class files?

    I will follow your advice and try to continue working on this great project.

    Yours sincerely,
    Emilio

     
  • Davide Bucci
    Davide Bucci
    2011-11-08

    Dear Emilio,
    of course, what it is interesting is the source code.
    I think you are not yet acquainted with Subversion, which is the source code
    versioning tool used for maintaining the repository of FidoCadJ:

    http://en.wikipedia.org/wiki/Apache_Subversion

    Before trying to commit anything to FidoCadJ, I strongly suggest you try to
    play a little bit with Subversion, for example following one of the many
    tutorials existing for that software.
    Just be sure you know what you do before committing anything to FidoCadJ (i.e.
    do not use the FidoCadJ svn repository to do your tests while learning how svn
    is working).

    Many thanks and best regards,

    D.

     
  • Emilio
    Emilio
    2011-11-08

    Dear Davide,

    Just committed my code. Please let my know if I did something wrong, this is
    the first time I contributed to a project. It was very exciting :D I will be
    happy to continue working with you.

    Thank you very much for your support,
    Emilio

     
  • Davide Bucci
    Davide Bucci
    2011-11-08

    Dear Emilio,
    congratulations, your commits were successful :-)

    I had a look at your code and I have a few remarks.
    The first one is that you used some generics when using the hash table and the
    ArrayList in the code you wrote.
    Even if this is indeed a good practice, it is not supported by Java 1.4 and
    FidoCadJ still retains the compatibility with this version of the JRE, to
    ensure that it can be run on a very wide variety of legacy systems.
    The code used in the scripts for compiling FidoCadJ is as follows:

    javac  -g -O -sourcepath src -classpath bin -source 1.4 -target 1.4 ./src/FidoMain.java -d bin
    

    As you can see, your code is not supported by the 1.4 version of Java.
    Can you please modify your code in order that it can be run with the scripts
    provided for the compilation (see paragraph 2 of the README file)? Remember
    that a commit should not break the build, so everyone should compile FidoCadJ
    with any of the version contained in the repository (as we seen, version 221
    is not runnable with JRE 1.4 and I am wondering if version 220 can be built,
    since you added the ToolButton class in a second moment). This is a very
    important point.

    My second remark is more technical and it may be a matter of programming
    tastes. I see that you are using an iterator to navigate through the array you
    created containing the buttons. Your version of the getSelectionState() and
    similar methods is much cleaner than the old one. This is a very good idea. I
    was wandering if it is still useful to keep a separate variable for all
    button:

        //Instance variable of each button
        private JToggleButton selection;
        private JToggleButton zoom;
        private JToggleButton hand;  
        private JToggleButton line;
        private JToggleButton advtext;
        private JToggleButton bezier;
        private JToggleButton polygon;
        private JToggleButton ellipse;
        private JToggleButton rectangle;
        private JToggleButton connection;    
        private JToggleButton pcbline;
        private JToggleButton pcbpad;
    

    Don't you think the toolButtonsList is enough?

    Finally, when writing the Javadoc comments, keep in mind that those comments
    should be kept easily readable even when you are looking at the code source
    (for example, since I am acquainted with the codebase, I do use very rarely a
    browser to navigate through the results given by Javadoc). Putting some tags
    is OK, but try to keep those comments easily readable even before having been
    processed. A good thing when using multi line comments is to put a blank line
    sometimes, to visually separate paragraphs.

    In any case, you did a good work and I am learning some interesting techniques
    from your code. However, can you please make sort that it can be compiled with
    a JVM 1.4 (you will be required to add some ugly explicit casts to avoid
    generics and convert the style of the for loop)?

    If you would like to continue coding on FidoCadJ, if you navigate through the
    source code, you will notice that some of the user interface code would
    benefit from a little bit of refactoring :-) Just be careful not to make grow
    the number of classes too much and resist to the temptation of using the
    Extract class refactoring too much. In my experience, having an excessive
    granularity of the code can become difficult to handle, unless there are good
    reasons to proceed this way.

    So thanks again and I hope you want to continue to collaborate to the FidoCadJ
    project!

    D.

     
  • Emilio
    Emilio
    2011-11-09

    Dear Davide,

    I added casts and modified loops to avoid generics. However, I cannot check if
    the code is now supported by the 1.4 version of Java, scripts do not run
    properly on my machine, neither does the code you showed. Could you please
    check this for me?

    I tried getting rid of the instance variables for each button, but then these
    buttons cannot be accessed by the actionPerformed methods (inner classes). I
    will try to find a solution for this. I slightly modified the Javadoc comments
    as you suggested.

    Do not hesitate to ask me anything else. I will follow your advice in future
    contributions.

    Thank you very much,
    Emilio

     
  • Davide Bucci
    Davide Bucci
    2011-11-09

    Dear Emilio,
    I still get errors when I compile with Java 1.4:

    [davidebucci@Darwin-iMac-G5]$ ./rebuild mac
    src/toolbars/ToolbarTools.java:121: cannot find symbol
    symbol  : method put(javax.swing.JToggleButton,int)
    location: class java.util.HashMap
            circuitPanelConstants.put(button, circuitPanelConstant);
                                 ^
    src/toolbars/ToolbarTools.java:169: inconvertible types
    found   : java.lang.Integer
    required: int
                    setSelectionState((int)(Integer) circuitPanelConstants.get(selection),"");
                                           ^
    src/toolbars/ToolbarTools.java:185: inconvertible types
    found   : java.lang.Integer
    required: int
                    setSelectionState((int)(Integer) circuitPanelConstants.get(zoom),"");
                                           ^
    src/toolbars/ToolbarTools.java:200: inconvertible types
    found   : java.lang.Integer
    required: int
                    setSelectionState((int)(Integer) circuitPanelConstants.get(hand),"");
                                           ^
    src/toolbars/ToolbarTools.java:215: inconvertible types
    found   : java.lang.Integer
    required: int
                    setSelectionState((int)(Integer) circuitPanelConstants.get(line),"");
                                           ^
    src/toolbars/ToolbarTools.java:230: inconvertible types
    found   : java.lang.Integer
    required: int
                    setSelectionState((int)(Integer) circuitPanelConstants.get(advtext),"");
                                           ^
    src/toolbars/ToolbarTools.java:245: inconvertible types
    found   : java.lang.Integer
    required: int
                    setSelectionState((int)(Integer) circuitPanelConstants.get(bezier),"");
                                           ^
    src/toolbars/ToolbarTools.java:260: inconvertible types
    found   : java.lang.Integer
    required: int
                    setSelectionState((int)(Integer) circuitPanelConstants.get(polygon),"");
                                           ^
    src/toolbars/ToolbarTools.java:275: inconvertible types
    found   : java.lang.Integer
    required: int
                    setSelectionState((int)(Integer) circuitPanelConstants.get(ellipse),"");
                                           ^
    src/toolbars/ToolbarTools.java:290: inconvertible types
    found   : java.lang.Integer
    required: int
                    setSelectionState((int)(Integer) circuitPanelConstants.get(rectangle),"");
                                           ^
    src/toolbars/ToolbarTools.java:305: inconvertible types
    found   : java.lang.Integer
    required: int
                    setSelectionState((int)(Integer) circuitPanelConstants.get(connection),"");
                                           ^
    src/toolbars/ToolbarTools.java:320: inconvertible types
    found   : java.lang.Integer
    required: int
                    setSelectionState((int)(Integer) circuitPanelConstants.get(pcbline),"");
                                           ^
    src/toolbars/ToolbarTools.java:335: inconvertible types
    found   : java.lang.Integer
    required: int
                    setSelectionState((int)(Integer) circuitPanelConstants.get(pcbpad),"");
                                           ^
    src/toolbars/ToolbarTools.java:387: inconvertible types
    found   : java.lang.Integer
    required: int
                return (int)(Integer) circuitPanelConstants.get(selectedButton);
                            ^
    src/toolbars/ToolbarTools.java:412: inconvertible types
    found   : java.lang.Integer
    required: int
                int circuitPanelConstant = (int)(Integer) circuitPanelConstants.get(button);
                                                ^
    Note: src/FidoFrame.java uses or overrides a deprecated API.
    Note: Recompile with -Xlint:deprecation for details.
    15 errors
    

    The most important thing is to make sort that you can test your code on Java
    1.4. You should see how to obtain this with your Java compiler. See for
    example the -target and the -source flags:

    http://download.oracle.com/javase/1.5.0/docs/tooldocs/windows/javac.html

    In any case, I tried to compile your code with Java 1.5 and it runs fine.

    Regards,

    D.

     
  • Emilio
    Emilio
    2011-11-09

    Dear Davide,

    I believe the class compiles now on Java 1.4. Could you check it too just to
    be sure?

    Thank you very much,
    Emilio

     
  • Davide Bucci
    Davide Bucci
    2011-11-09

    Dear Emilio,
    I think it is perfect now!

    Everything seem to work fine. Good job!
    If you like to continue to refactor other classes like you did with
    ToolbarTools, that would be very useful!

    So thanks again and I hope that you will decide to continue to participate to
    the coding activity!

    Regards,

    D.

     
  • Emilio
    Emilio
    2011-11-09

    Dear Davide,

    =) Thank you. I re-committed the code as some lines were longer than 80
    characters.

    Thank you so much, this really helped me with my university project.

    Best regards,
    Emilio

     
  • Davide Bucci
    Davide Bucci
    2011-11-10

    Dear Emilio,
    I am happy this helped you for your university project. It is a nice
    initiative of your professors to encourage their students to participate to
    open source projects.

    In any case, it would be a pleasure to continue to collaborate together to the
    FidoCadJ project.

    Best regards,

    Davide

     
  • Emilio
    Emilio
    2011-11-10

    Dear Davide,

    Sure, I already have some ideas in mind, I'll do my best.

    Thank you very much for giving me this opportunity,
    Emilio

     
  • Davide Bucci
    Davide Bucci
    2011-11-11

    Dear Emilio,
    I reformatted a little bit the Javadoc comments. Now, I think the two classes
    are on exactly the same style of the rest of the program.

    While reading your code, I have another technical question. I see that each
    instance of a ToolButton contains a JToggleButton object. I was wandering if
    it would not be cleaner to make ToolButton a child class derived from
    JToggleButton? After all, a ToolButton is a button and adds some
    functionalities to the standard JToggleButton.
    This would allow to get rid of commands like this one:

    selection = selectionToolButton.getToolButton();
    

    since you just need to declare selection as an instance of ToolButton as a
    private member of ToolbarTools, and using it also at the place of
    selectionToolButton.

    What do you think of that?

    Thank you again and best regards.

    D.

     
  • Emilio
    Emilio
    2011-11-13

    Dear Davide,

    I think that's a great idea. I wasn't convinced by the way I had implemented
    that part either. I will look at it as soon as possible and show you my work
    here before commiting anything.

    Thanks,
    Emilio

     
  • Davide Bucci
    Davide Bucci
    2011-12-17

    Dear josmil1,
    any news? Were you able to implement what I suggested?

    Best regards,

    D.

     
  • Emilio
    Emilio
    2011-12-27

    Dear Davide,

    Sorry for the delay in replying to your message, this month I have been very
    busy with exams and then the holidays. I have been working on your suggestions
    for a while, but I am finding it quite difficult, I'm not sure I totally
    understand what I need to do.

    Thanks (and merry Christmas!),
    Emilio

     
  • Davide Bucci
    Davide Bucci
    2011-12-27

    Dear Emilio,
    do not feel obliged to work on the ToolbarTools further refactoring.
    Now the code is working reliably and it is understandable. However, if you
    would like to continue to participate to the FidoCadJ project, I am sure there
    are other places where a little bit of cleanup might be beneficial.
    If you feel difficult to improve the ToolbarTools class, feel free to have a
    look on other classes, to see if you can improve them.
    If you find something you think you can do, the best thing to do is to open a
    new discussion here describing what you want to do and why. We will try to
    decide some structural changes together and then you might do the refactoring.

    Thanks a lot; given the period, if you have some vacations I hope you are
    enjoying them. Thanks a lot for the wishes and have an happy new year!

    Best regards,

    D.

     


Anonymous


Cancel   Add attachments