Skip to content

Commit

Permalink
Merge pull request #55 from Nilon123456789/Localization
Browse files Browse the repository at this point in the history
Localization support (Issue #54)
  • Loading branch information
dheid authored Apr 19, 2024
2 parents 43416a2 + 340db87 commit aaa5c47
Show file tree
Hide file tree
Showing 16 changed files with 319 additions and 47 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,24 @@ colorPicker.addColorListener(colorModel -> System.out.println(colorModel.getColo

This creates a color picker component with expert controls and opacity settings. If the user selects a color, the color listener will be notified.

### :globe_with_meridians: Localization

The color picker supports localization. You can set the locale by passing it to the constructor:

```java
ColorPicker colorPicker = new ColorPicker(true, true, Locale.FRENCH);
// or
ColorPickerDialog.showDialog(null, Color.GREEN, Locale.FRENCH);
```

Currently, the following languages are supported:
- English
- Español
- Français
- Deutsch
- Português
- Русский

## :hammer: Building

Please use Maven to build and test the project.
Expand Down
64 changes: 50 additions & 14 deletions src/main/java/com/bric/colorpicker/ColorPicker.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.util.Locale;
import java.util.ResourceBundle;
import javax.swing.ButtonGroup;
import javax.swing.JComponent;
Expand Down Expand Up @@ -102,27 +103,32 @@ public class ColorPicker extends JPanel {
private static final String MODE_CONTROLS_VISIBLE_PROPERTY = "mode controls visible";

/**
* The localized STRINGS used in this (and related) panel(s).
* Path to the localization bundle
*/
private static final ResourceBundle strings = ResourceBundle.getBundle("com.bric.colorpicker.resources.ColorPicker");
private static final String LOCALIZATION_BUNDLE_PATH = "com.bric.colorpicker.resources.ColorPicker";

/**
* The localized STRINGS used in this (and related) panel(s).
*/
private final ResourceBundle strings;
private final ColorModel colorModel = new ColorModel();
private final ModeModel modeModel = new ModeModel();
private final ColorSlider slider = new ColorSlider();
private final Option alphaOption = new AlphaOption();
private final Option hueOption = new HueOption();
private final Option saturationOption = new SaturationOption();
private final Option brightnessOption = new BrightnessOption();
private final Option redOption = new RedOption();
private final Option greenOption = new GreenOption();
private final Option blueOption = new BlueOption();
private final ColorSwatch preview = new ColorSwatch(50);
private final JLabel hexLabel = new JLabel(strings.getObject("hexLabel").toString());
private final Option alphaOption;
private final Option hueOption;
private final Option saturationOption;
private final Option brightnessOption;
private final Option redOption;
private final Option greenOption;
private final Option blueOption;
private final HexField hexField = new HexField();
private final JPanel expertControls = new JPanel(new GridBagLayout());
private final ColorPickerPanel colorPanel = new ColorPickerPanel();
private final OpacitySlider opacitySlider = new OpacitySlider();
private final JLabel opacityLabel = new JLabel(strings.getObject("opacityLabel").toString());

private final ColorSwatch preview;
private final JLabel hexLabel;
private final JLabel opacityLabel;

/**
* Create a new {@code ColorPicker} with all controls visible except opacity.
Expand All @@ -131,6 +137,14 @@ public ColorPicker() {
this(true, false);
}

/**
* Create a new {@code ColorPicker} with all controls visible except opacity with the active local
* @param local the current active local of the app
*/
public ColorPicker(Locale local) {
this(true, false, local);
}

/**
* Create a new {@code ColorPicker}.
*
Expand All @@ -142,9 +156,25 @@ public ColorPicker() {
* @param includeOpacity whether the opacity controls will be shown
*/
public ColorPicker(boolean showExpertControls, boolean includeOpacity) {
this(showExpertControls, includeOpacity, null);
}

/**
* Create a new {@code ColorPicker}.
*
* @param showExpertControls the labels/spinners/buttons on the right side of a
* {@code ColorPicker} are optional. This boolean will control whether they
* are shown or not.
* <P>It may be that your users will never need or want numeric control when
* they choose their colors, so hiding this may simplify your interface.
* @param includeOpacity whether the opacity controls will be shown
* @param locale the current active local of the app
*/
public ColorPicker(boolean showExpertControls, boolean includeOpacity, Locale locale) {
super(new GridBagLayout());

initNames();
if(locale == null) strings = ResourceBundle.getBundle(LOCALIZATION_BUNDLE_PATH);
else strings = ResourceBundle.getBundle(LOCALIZATION_BUNDLE_PATH, locale);

GridBagConstraints constraints = new GridBagConstraints();

Expand All @@ -159,7 +189,7 @@ public ColorPicker(boolean showExpertControls, boolean includeOpacity) {
ButtonGroup buttonGroup = new ButtonGroup();

Option[] options = {
hueOption, saturationOption, brightnessOption, redOption, greenOption, blueOption
hueOption = new HueOption(locale), saturationOption = new SaturationOption(locale), brightnessOption = new BrightnessOption(locale), redOption = new RedOption(locale), greenOption = new GreenOption(locale), blueOption = new BlueOption(locale)
};

for (int optionIndex = 0; optionIndex < options.length; optionIndex++) {
Expand All @@ -173,13 +203,15 @@ public ColorPicker(boolean showExpertControls, boolean includeOpacity) {
constraints.insets = new Insets(normalInsets.top + 10, normalInsets.left, normalInsets.bottom, normalInsets.right);
constraints.anchor = GridBagConstraints.LINE_END;
constraints.fill = GridBagConstraints.NONE;
this.hexLabel = new JLabel(strings.getObject("hexLabel").toString());
optionsPanel.add(hexLabel, constraints);

constraints.gridx++;
constraints.anchor = GridBagConstraints.LINE_START;
constraints.fill = GridBagConstraints.HORIZONTAL;
optionsPanel.add(hexField, constraints);

alphaOption = new AlphaOption(locale);
alphaOption.addTo(optionsPanel, constraints);

constraints.gridx = 0;
Expand Down Expand Up @@ -214,6 +246,7 @@ public ColorPicker(boolean showExpertControls, boolean includeOpacity) {
constraints.weighty = 0;
constraints.insets = normalInsets;
constraints.anchor = GridBagConstraints.CENTER;
this.opacityLabel = new JLabel(strings.getObject("opacityLabel").toString());
add(opacityLabel, constraints);

constraints.gridx++;
Expand All @@ -231,6 +264,7 @@ public ColorPicker(boolean showExpertControls, boolean includeOpacity) {
constraints.weightx = 1;
constraints.anchor = GridBagConstraints.PAGE_START;
constraints.insets = new Insets(normalInsets.top, normalInsets.left + 8, normalInsets.bottom + 10, normalInsets.right + 8);
this.preview = new ColorSwatch(50, locale);
expertControls.add(preview, constraints);

constraints.gridy++;
Expand All @@ -239,6 +273,8 @@ public ColorPicker(boolean showExpertControls, boolean includeOpacity) {
constraints.insets = new Insets(normalInsets.top, normalInsets.left, 0, normalInsets.right);
expertControls.add(optionsPanel, constraints);

initNames();

initializeColorPanel();
initializeSlider();
initializePreview();
Expand Down
76 changes: 63 additions & 13 deletions src/main/java/com/bric/colorpicker/ColorPickerDialog.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Locale;
import java.util.ResourceBundle;
import javax.swing.JComponent;
import javax.swing.JDialog;
Expand All @@ -44,7 +45,7 @@
*/
public class ColorPickerDialog extends JDialog {

private static final ResourceBundle STRINGS = ResourceBundle.getBundle("com.bric.colorpicker.resources.ColorPickerDialog");
private static final String LOCALIZATION_BUNDLE_PATH = "com.bric.colorpicker.resources.ColorPickerDialog";
public static final JComponent[] LEFT_COMPONENTS = new JComponent[0];

private ColorPicker colorPicker;
Expand All @@ -56,13 +57,25 @@ public ColorPickerDialog() {
}

public ColorPickerDialog(Frame owner, Color color, boolean includeOpacity) {
super(owner);
initialize(owner, color, includeOpacity);
this(owner, color, includeOpacity, null);
}

public ColorPickerDialog(Dialog owner, Color color, boolean includeOpacity) {
this(owner, color, includeOpacity, null);
}

public ColorPickerDialog(Locale locale) {
this((Frame) null, Color.BLUE, false, locale);
}

public ColorPickerDialog(Frame owner, Color color, boolean includeOpacity, Locale locale) {
super(owner);
initialize(owner, color, includeOpacity);
initialize(owner, color, includeOpacity, locale);
}

public ColorPickerDialog(Dialog owner, Color color, boolean includeOpacity, Locale locale) {
super(owner);
initialize(owner, color, includeOpacity, locale);
}

/**
Expand All @@ -74,21 +87,26 @@ public ColorPickerDialog(Dialog owner, Color color, boolean includeOpacity) {
* @param title the title for the dialog.
* @param originalColor the color the {@code ColorPicker} initially points to.
* @param includeOpacity whether to add a control for the opacity of the color.
* @param locale the current active local of the app
* @return the {@code Color} the user chooses, or {@code null} if the user cancels the dialog.
*/
public static Color showDialog(Window owner, String title, Color originalColor, boolean includeOpacity) {
public static Color showDialog(Window owner, String title, Color originalColor, boolean includeOpacity, Locale locale) {
ColorPickerDialog dialog;
ResourceBundle strings;

if(locale == null) strings = ResourceBundle.getBundle(LOCALIZATION_BUNDLE_PATH);
else strings = ResourceBundle.getBundle(LOCALIZATION_BUNDLE_PATH, locale);

if (owner instanceof Frame || owner == null) {
dialog = new ColorPickerDialog((Frame) owner, originalColor, includeOpacity);
dialog = new ColorPickerDialog((Frame) owner, originalColor, includeOpacity, locale);
} else if (owner instanceof Dialog) {
dialog = new ColorPickerDialog((Dialog) owner, originalColor, includeOpacity);
dialog = new ColorPickerDialog((Dialog) owner, originalColor, includeOpacity, locale);
} else {
throw new IllegalArgumentException("the owner (" + owner.getClass().getName() + ") must be a java.awt.Frame or a java.awt.Dialog");
}

if (title == null) {
dialog.setTitle(STRINGS.getObject("ColorPickerDialogTitle").toString());
dialog.setTitle(strings.getObject("ColorPickerDialogTitle").toString());
} else {
dialog.setTitle(title);
}
Expand All @@ -110,7 +128,23 @@ public static Color showDialog(Window owner, String title, Color originalColor,
* @return the {@code Color} the user chooses, or {@code null} if the user cancels the dialog.
*/
public static Color showDialog(Window owner, Color originalColor, boolean includeOpacity) {
return showDialog(owner, null, originalColor, includeOpacity);
return showDialog(owner, null, originalColor, includeOpacity, null);
}

/**
* This creates a modal dialog prompting the user to select a color.
* <P>This uses a generic dialog title: "Choose a Color".
*
* @param owner the dialog this new dialog belongs to. This must be a Frame or a Dialog.
* Java 1.6 supports Windows here, but this package is designed/compiled to work in Java 1.4,
* so an {@code IllegalArgumentException} will be thrown if this target is a {@code Window}.
* @param originalColor the color the {@code ColorPicker} initially points to.
* @param includeOpacity whether to add a control for the opacity of the color.
* @param local the current active local of the app
* @return the {@code Color} the user chooses, or {@code null} if the user cancels the dialog.
*/
public static Color showDialog(Window owner, Color originalColor, boolean includeOpacity, Locale locale) {
return showDialog(owner, null, originalColor, includeOpacity, locale);
}

/**
Expand All @@ -124,11 +158,27 @@ public static Color showDialog(Window owner, Color originalColor, boolean includ
* @return the {@code Color} the user chooses, or {@code null} if the user cancels the dialog.
*/
public static Color showDialog(Window owner, Color originalColor) {
return showDialog(owner, null, originalColor, false);
return showDialog(owner, null, originalColor, false, null);
}

private void initialize(Component owner, Color color, boolean includeOpacity) {
colorPicker = new ColorPicker(true, includeOpacity);
/**
* This creates a modal dialog prompting the user to select a color.
* <P>This uses a generic dialog title: "Choose a Color", and does not include opacity.
*
* @param owner the dialog this new dialog belongs to. This must be a Frame or a Dialog.
* Java 1.6 supports Windows here, but this package is designed/compiled to work in Java 1.4,
* so an {@code IllegalArgumentException} will be thrown if this target is a {@code Window}.
* @param originalColor the color the {@code ColorPicker} initially points to.
* @param locale the current active local of the app
* @return the {@code Color} the user chooses, or {@code null} if the user cancels the dialog.
*/
public static Color showDialog(Window owner, Color originalColor, Locale locale) {
return showDialog(owner, null, originalColor, false, locale);
}

private void initialize(Component owner, Color color, boolean includeOpacity, Locale locale) {

colorPicker = new ColorPicker(true, includeOpacity, locale);
setModal(true);
setResizable(false);
getContentPane().setLayout(new GridBagLayout());
Expand All @@ -143,7 +193,7 @@ private void initialize(Component owner, Color color, boolean includeOpacity) {
getContentPane().add(colorPicker, constraints);
constraints.gridy++;
DialogFooter footer = DialogFooter.createDialogFooter(LEFT_COMPONENTS,
DialogFooter.OK_CANCEL_OPTION, DialogFooter.OK_OPTION, EscapeKeyBehavior.TRIGGERS_CANCEL);
DialogFooter.OK_CANCEL_OPTION, DialogFooter.OK_OPTION, EscapeKeyBehavior.TRIGGERS_CANCEL, locale);
constraints.gridy++;
constraints.weighty = 0;
getContentPane().add(footer, constraints);
Expand Down
7 changes: 6 additions & 1 deletion src/main/java/com/bric/colorpicker/options/AlphaOption.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,16 @@
import javax.swing.ButtonGroup;
import java.awt.Container;
import java.awt.GridBagConstraints;
import java.util.Locale;

public class AlphaOption extends Option {

public AlphaOption() {
super(STRINGS.getObject("alphaLabel").toString(), ColorPickerMode.ALPHA);
this(null);
}

public AlphaOption(Locale locale) {
super("alphaLabel", ColorPickerMode.ALPHA, locale);
}

@Override
Expand Down
8 changes: 7 additions & 1 deletion src/main/java/com/bric/colorpicker/options/BlueOption.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
package com.bric.colorpicker.options;

import java.util.Locale;

import com.bric.colorpicker.ColorPickerMode;
import com.bric.colorpicker.models.ColorModel;

public class BlueOption extends Option {

public BlueOption() {
super(STRINGS.getObject("blueLabel").toString(), ColorPickerMode.BLUE);
this(null);
}

public BlueOption(Locale locale) {
super("blueLabel", ColorPickerMode.BLUE, locale);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
package com.bric.colorpicker.options;

import java.util.Locale;

import com.bric.colorpicker.ColorPickerMode;
import com.bric.colorpicker.models.ColorModel;

public class BrightnessOption extends Option {

public BrightnessOption() {
super(STRINGS.getObject("brightnessLabel").toString(), ColorPickerMode.BRIGHTNESS);
this(null);
}

public BrightnessOption(Locale locale) {
super("brightnessLabel", ColorPickerMode.BRIGHTNESS, locale);
}

@Override
Expand Down
8 changes: 7 additions & 1 deletion src/main/java/com/bric/colorpicker/options/GreenOption.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
package com.bric.colorpicker.options;

import java.util.Locale;

import com.bric.colorpicker.ColorPickerMode;
import com.bric.colorpicker.models.ColorModel;

public class GreenOption extends Option {

public GreenOption() {
super(STRINGS.getObject("greenLabel").toString(), ColorPickerMode.GREEN);
this(null);
}

public GreenOption(Locale locale) {
super("greenLabel", ColorPickerMode.GREEN, locale);
}

@Override
Expand Down
Loading

0 comments on commit aaa5c47

Please sign in to comment.