001    /*
002     * UniformPaletteQuantizerDialog
003     * 
004     * Copyright (c) 2001, 2002, 2003 Marco Schmidt.
005     * All rights reserved.
006     */
007    
008    package net.sourceforge.jiu.gui.awt.dialogs;
009    
010    import java.awt.BorderLayout;
011    import java.awt.Button;
012    import java.awt.Choice;
013    import java.awt.Dialog;
014    import java.awt.Dimension;
015    import java.awt.Frame;
016    import java.awt.GridLayout;
017    import java.awt.Label;
018    import java.awt.Panel;
019    import java.awt.Rectangle;
020    import java.awt.Scrollbar;
021    import java.awt.Toolkit;
022    import java.awt.event.ActionEvent;
023    import java.awt.event.ActionListener;
024    import java.awt.event.AdjustmentEvent;
025    import java.awt.event.AdjustmentListener;
026    import java.awt.event.ItemEvent;
027    import java.awt.event.ItemListener;
028    import net.sourceforge.jiu.apps.Strings;
029    
030    /**
031     * An AWT dialog to enter the parameters for a uniform palette color quantization operation.
032     * @author Marco Schmidt
033     */
034    public class UniformPaletteQuantizerDialog extends Dialog implements ActionListener, AdjustmentListener, ItemListener
035    {
036            public static final int TYPE_DITHERING_NONE = 0;
037            public static final int TYPE_ORDERED_DITHERING = 1;
038            public static final int TYPE_FLOYD_STEINBERG_ERROR_DIFFUSION = 2;
039            public static final int TYPE_STUCKI_ERROR_DIFFUSION = 3;
040            public static final int TYPE_BURKES_ERROR_DIFFUSION = 4;
041            public static final int TYPE_SIERRA_ERROR_DIFFUSION = 5;
042            public static final int TYPE_JARVIS_JUDICE_NINKE_ERROR_DIFFUSION = 6;
043            public static final int TYPE_STEVENSON_ARCE_ERROR_DIFFUSION = 7;
044            public final int[][] DITHERING_METHODS =
045            {
046                    {
047                     TYPE_DITHERING_NONE,
048                     TYPE_ORDERED_DITHERING,
049                     TYPE_FLOYD_STEINBERG_ERROR_DIFFUSION,
050                     TYPE_STUCKI_ERROR_DIFFUSION,
051                     TYPE_BURKES_ERROR_DIFFUSION,
052                     TYPE_SIERRA_ERROR_DIFFUSION,
053                     TYPE_JARVIS_JUDICE_NINKE_ERROR_DIFFUSION,
054                     TYPE_STEVENSON_ARCE_ERROR_DIFFUSION
055                    },
056                    {
057                     Strings.DITHERING_NONE,
058                     Strings.ORDERED_DITHERING,
059                     Strings.FLOYD_STEINBERG_ERROR_DIFFUSION,
060                     Strings.STUCKI_ERROR_DIFFUSION,
061                     Strings.BURKES_ERROR_DIFFUSION,
062                     Strings.SIERRA_ERROR_DIFFUSION,
063                     Strings.JARVIS_JUDICE_NINKE_ERROR_DIFFUSION,
064                     Strings.STEVENSON_ARCE_ERROR_DIFFUSION
065                    }
066            };
067            private Strings strings;
068            private Button ok;
069            private Button cancel;
070            private Scrollbar redScrollbar;
071            private Scrollbar greenScrollbar;
072            private Scrollbar blueScrollbar;
073            private Choice ditheringMethod;
074            private Label infoLabel1;
075            private Label infoLabel2;
076            private Label redLabel;
077            private Label greenLabel;
078            private Label blueLabel;
079            private boolean pressedOk;
080    
081            /**
082             * Creates a modal dialog to enter the parameter.
083             * @param owner the parent of this modal dialog
084             * @param strings an object to get String constants in the current language
085             * @param redBits the initial selection of the number of bits for the red channel
086             * @param greenBits the initial selection of the number of bits for the green channel
087             * @param blueBits the initial selection of the number of bits for the blue channel
088             * @param ditheringMethodSelection initial selection for dithering method
089             */
090            public UniformPaletteQuantizerDialog(Frame owner, Strings strings, int redBits, 
091                    int greenBits, int blueBits, int ditheringMethodSelection)
092            {
093                    super(owner, strings.get(Strings.UNIFORM_PALETTE_COLOR_QUANTIZATION), true);
094                    pressedOk = false;
095                    this.strings = strings;
096                    Panel panel = new Panel();
097                    panel.setLayout(new GridLayout(0, 2));
098    
099                    redLabel = new Label(strings.get(Strings.NUMBER_OF_BITS_RED));
100                    panel.add(redLabel);
101                    redScrollbar = new Scrollbar(Scrollbar.HORIZONTAL, redBits, 1, 1, 7);
102                    redScrollbar.addAdjustmentListener(this);
103                    panel.add(redScrollbar);
104    
105                    greenLabel = new Label(strings.get(Strings.NUMBER_OF_BITS_GREEN));
106                    panel.add(greenLabel);
107                    greenScrollbar = new Scrollbar(Scrollbar.HORIZONTAL, greenBits, 1, 1, 7);
108                    greenScrollbar.addAdjustmentListener(this);
109                    panel.add(greenScrollbar);
110    
111                    blueLabel = new Label(strings.get(Strings.NUMBER_OF_BITS_BLUE));
112                    panel.add(blueLabel);
113                    blueScrollbar = new Scrollbar(Scrollbar.HORIZONTAL, blueBits, 1, 1, 7);
114                    blueScrollbar.addAdjustmentListener(this);
115                    panel.add(blueScrollbar);
116    
117                    infoLabel1 = new Label();
118                    infoLabel2 = new Label();
119                    panel.add(infoLabel1);
120                    panel.add(infoLabel2);
121    
122                    panel.add(new Label(strings.get(Strings.DITHERING_METHOD)));
123                    ditheringMethod = new Choice();
124                    for (int i = 0; i < DITHERING_METHODS[0].length; i++)
125                    {
126                            ditheringMethod.add(strings.get(DITHERING_METHODS[1][i]));
127                            if (ditheringMethodSelection == i)
128                            {
129                                    ditheringMethod.select(i);
130                            }
131                    }
132                    ditheringMethod.addItemListener(this);
133                    panel.add(ditheringMethod);
134    
135                    add(panel, BorderLayout.CENTER);
136    
137                    ok = new Button(strings.get(Strings.OK));
138                    ok.addActionListener(this);
139                    cancel = new Button(strings.get(Strings.CANCEL));
140                    cancel.addActionListener(this);
141    
142                    panel = new Panel();
143                    panel.add(ok);
144                    panel.add(cancel);
145                    add(panel, BorderLayout.SOUTH);
146    
147                    updateLabels();
148    
149                    pack();
150                    center();
151            }
152    
153            /**
154             * Hides (closes) this dialog if the OK button was source of the action event
155             * (e.g. if the button was pressed).
156             */
157            public void actionPerformed(ActionEvent e)
158            {
159                    if (e.getSource() == ok)
160                    {
161                            pressedOk = true;
162                            setVisible(false);
163                    }
164                    else
165                    if (e.getSource() == cancel)
166                    {
167                            setVisible(false);
168                    }
169            }
170    
171            public void adjustmentValueChanged(AdjustmentEvent e)
172            {
173                    updateLabels();
174            }
175    
176            /**
177             * Centers the dialog on screen.
178             */
179            public void center()
180            {
181                    Rectangle rect = getBounds();
182                    int width = rect.width;
183                    int height = rect.height;
184                    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
185                    setLocation((screenSize.width / 2) - (width / 2),
186                            (screenSize.height / 2) - (height / 2));
187            }
188    
189            /*public int getNumColors()
190            {
191                    return getValue(numColorsField);
192            }*/
193    
194            public int getDitheringMethod()
195            {
196                    return DITHERING_METHODS[0][ditheringMethod.getSelectedIndex()];
197            }
198    
199            public int getBlueBits()
200            {
201                    return blueScrollbar.getValue();
202            }
203    
204            public int getGreenBits()
205            {
206                    return greenScrollbar.getValue();
207            }
208    
209            public int getRedBits()
210            {
211                    return redScrollbar.getValue();
212            }
213    
214            public boolean hasPressedOk()
215            {
216                    return pressedOk;
217            }
218    
219            public boolean isSelectionValid()
220            {
221                    int r = getRedBits();
222                    int g = getGreenBits();
223                    int b = getBlueBits();
224                    int sum = r + g + b;
225                    if (getDitheringMethod() == TYPE_DITHERING_NONE)
226                    {
227                            return (sum < 9);
228                    }
229                    else
230                    {
231                            return (sum < 24);
232                    }
233            }
234    
235            public void itemStateChanged(ItemEvent e)
236            {
237                    if (e.getSource() == ditheringMethod)
238                    {
239                            updateLabels();
240                    }
241            }
242    
243            private void updateLabels()
244            {
245                    redLabel.setText(strings.get(Strings.NUMBER_OF_BITS_RED) + " (" + getRedBits() + ")");
246                    greenLabel.setText(strings.get(Strings.NUMBER_OF_BITS_GREEN) + " (" + getGreenBits() + ")");
247                    blueLabel.setText(strings.get(Strings.NUMBER_OF_BITS_BLUE) + " (" + getBlueBits() + ")");
248                    boolean valid = isSelectionValid();
249                    ok.setEnabled(valid);
250                    if (valid)
251                    {
252                            int totalBits = getRedBits() + getGreenBits() + getBlueBits();
253                            int totalColors = 1 << totalBits;
254                            infoLabel1.setText(strings.get(Strings.TOTAL_NUMBER_OF_BITS_AND_COLORS));
255                            infoLabel2.setText(Integer.toString(totalBits) + ", " + Integer.toString(totalColors));
256                    }
257                    else
258                    {
259                            infoLabel1.setText(strings.get(Strings.ERROR_NO_MORE_THAN_8_BITS));
260                            infoLabel2.setText("");
261                    }
262            }
263    }