Skip to content

Commit

Permalink
multiline/path text alignment
Browse files Browse the repository at this point in the history
  • Loading branch information
lbalazscs committed Jan 4, 2025
1 parent ccd3cf2 commit 027d7f9
Show file tree
Hide file tree
Showing 15 changed files with 478 additions and 133 deletions.
46 changes: 38 additions & 8 deletions src/main/java/pixelitor/filters/painters/TextSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
import pixelitor.Composition;
import pixelitor.Views;
import pixelitor.filters.gui.UserPreset;
import pixelitor.gui.utils.TextAlignment;
import pixelitor.gui.utils.AlignmentSelector;
import pixelitor.gui.utils.BoxAlignment;
import pixelitor.layers.TextLayer;
import pixelitor.utils.Messages;
import pixelitor.utils.Rnd;
Expand Down Expand Up @@ -59,6 +60,7 @@ public class TextSettings implements Serializable, Debuggable {
private static final String PRESET_KEY_COLOR = "color";
private static final String PRESET_KEY_ROTATION = "rotation";
private static final String PRESET_KEY_ALIGN = "align";
private static final String PRESET_KEY_MLP_ALIGN = "mlp_align";
private static final String PRESET_KEY_WATERMARK = "watermark";
private static final String PRESET_KEY_REL_LINE_HEIGHT = "rel_line_height";
private static final String PRESET_KEY_SX = "sx";
Expand All @@ -77,6 +79,7 @@ public class TextSettings implements Serializable, Debuggable {
private VerticalAlignment verticalAlignment;
private HorizontalAlignment horizontalAlignment;
private boolean watermark;
private int mlpAlignment;

private double rotation;
private double sx;
Expand All @@ -95,19 +98,21 @@ public TextSettings(String text, Font font, Color color,
AreaEffects effects,
HorizontalAlignment horizontalAlignment,
VerticalAlignment verticalAlignment,
int mlpAlignment,
boolean watermark, double rotation,
double relLineHeight,
double sx, double sy,
double shx, double shy,
Consumer<TextSettings> guiUpdateCallback) {
assert effects != null;

this.text = text;
this.areaEffects = effects;
this.color = color;
this.font = font;
this.horizontalAlignment = horizontalAlignment;
this.text = text;
this.verticalAlignment = verticalAlignment;
this.mlpAlignment = mlpAlignment;
this.watermark = watermark;
this.rotation = rotation;
this.relLineHeight = relLineHeight;
Expand All @@ -129,6 +134,8 @@ public TextSettings() {
text = DEFAULT_TEXT;
verticalAlignment = VerticalAlignment.CENTER;
watermark = false;
mlpAlignment = AlignmentSelector.LEFT;

rotation = 0;
relLineHeight = 1.0;
sx = 1.0;
Expand All @@ -149,6 +156,7 @@ private TextSettings(TextSettings other) {
color = other.color;
verticalAlignment = other.verticalAlignment;
horizontalAlignment = other.horizontalAlignment;
mlpAlignment = other.mlpAlignment;
watermark = other.watermark;
rotation = other.rotation;
relLineHeight = other.relLineHeight;
Expand All @@ -170,6 +178,10 @@ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundE
shx = 0.0;
shy = 0.0;
}
if (mlpAlignment == 0) {
// field not found in old pxc files
mlpAlignment = AlignmentSelector.LEFT;
}
}

public TextSettings copy() {
Expand All @@ -181,6 +193,7 @@ public void configurePainter(TransformedTextPainter painter) {
painter.setFont(font);
painter.setEffects(areaEffects);
painter.setAlignment(horizontalAlignment, verticalAlignment);
painter.setMLPAlignment(mlpAlignment);
painter.setRotation(rotation);
painter.setAdvancedSettings(relLineHeight, sx, sy, shx, shy);
}
Expand Down Expand Up @@ -212,6 +225,12 @@ public void randomize() {
color = Rnd.createRandomColor();
horizontalAlignment = Rnd.chooseFrom(HorizontalAlignment.values());
verticalAlignment = Rnd.chooseFrom(VerticalAlignment.values());
mlpAlignment = Rnd.chooseFrom(new int[]{
AlignmentSelector.LEFT,
AlignmentSelector.CENTER,
AlignmentSelector.RIGHT
});

watermark = Rnd.nextBoolean();
rotation = Rnd.nextDouble() * Math.PI * 2;
relLineHeight = 0.5 + Rnd.nextDouble();
Expand All @@ -226,6 +245,7 @@ public void saveStateTo(UserPreset preset) {
preset.putColor(PRESET_KEY_COLOR, color);
preset.putFloat(PRESET_KEY_ROTATION, (float) rotation);
preset.putInt(PRESET_KEY_ALIGN, getAlignment().ordinal());
preset.putInt(PRESET_KEY_MLP_ALIGN, mlpAlignment);

new FontInfo(font).saveStateTo(preset);

Expand All @@ -250,13 +270,14 @@ public void loadUserPreset(UserPreset preset) {
horizontalAlignment = HorizontalAlignment.values()[preset.getInt(PRESET_KEY_HOR_ALIGN)];
verticalAlignment = VerticalAlignment.values()[preset.getInt(PRESET_KEY_VER_ALIGN)];
} else {
TextAlignment alignment = TextAlignment.values()[alignIndex];
if (alignment == TextAlignment.PATH && !Views.getActiveComp().hasActivePath()) {
alignment = TextAlignment.CENTER_CENTER;
BoxAlignment alignment = BoxAlignment.values()[alignIndex];
if (alignment == BoxAlignment.PATH && !Views.getActiveComp().hasActivePath()) {
alignment = BoxAlignment.CENTER_CENTER;
}
horizontalAlignment = alignment.getHorizontal();
verticalAlignment = alignment.getVertical();
}
mlpAlignment = preset.getInt(PRESET_KEY_MLP_ALIGN);

font = new FontInfo(preset).createFont();

Expand Down Expand Up @@ -312,15 +333,23 @@ public void setFont(Font font) {
this.font = font;
}

public TextAlignment getAlignment() {
return TextAlignment.from(horizontalAlignment, verticalAlignment);
public BoxAlignment getAlignment() {
return BoxAlignment.from(horizontalAlignment, verticalAlignment);
}

public void setAlignment(TextAlignment newAlignment) {
public void setAlignment(BoxAlignment newAlignment) {
this.horizontalAlignment = newAlignment.getHorizontal();
this.verticalAlignment = newAlignment.getVertical();
}

public int getMLPAlignment() {
return mlpAlignment;
}

public void setMLPAlignment(int mlpAlignment) {
this.mlpAlignment = mlpAlignment;
}

public String getText() {
return text;
}
Expand Down Expand Up @@ -379,6 +408,7 @@ public DebugNode createDebugNode(String key) {
node.add(areaEffects.createDebugNode("effects"));
node.addDouble("rotation", rotation);
node.addBoolean("watermark", watermark);
node.addInt("multiline/path alignment", mlpAlignment);

return node;
}
Expand Down
94 changes: 64 additions & 30 deletions src/main/java/pixelitor/filters/painters/TextSettingsPanel.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2024 Laszlo Balazs-Csiki and Contributors
* Copyright 2025 Laszlo Balazs-Csiki and Contributors
*
* This file is part of Pixelitor. Pixelitor is free software: you
* can redistribute it and/or modify it under the terms of the GNU
Expand Down Expand Up @@ -69,14 +69,19 @@ public class TextSettingsPanel extends FilterGUI
private JCheckBox italicCB;
private ColorParam color;
private EffectsPanel effectsPanel;
private JComboBox<TextAlignment> alignmentCB;
private JComboBox<BoxAlignment> boxAlignmentCB;
private JCheckBox watermarkCB;

private JDialog advancedSettingsDialog;
private AdvancedTextSettingsPanel advancedSettingsPanel;

private boolean suppressGuiUpdates = false;
private TextAlignment lastAlignment;
private BoxAlignment lastBoxAlignment;

// multiline/path alignment settings
private boolean hasMLPAlign = true;
private AlignmentSelector mlpAlignmentSelector;
private JLabel mlpLabel;

/**
* Used for the text filter on images
Expand Down Expand Up @@ -134,34 +139,46 @@ private JPanel createTextPanel(TextSettings settings, Composition comp) {

gbh.addLabel("Color:", 0, 1);
color = new ColorParam("Color", settings.getColor(), USER_ONLY_TRANSPARENCY);
gbh.addControl(color.createGUI());
color.setAdjustmentListener(this);

gbh.addLabel("Rotation:", 2, 1);
JPanel colorRotPanel = new JPanel(new FlowLayout(LEFT));
colorRotPanel.add(color.createGUI());
colorRotPanel.add(new JLabel(" Rotation:"));
rotationParam = new AngleParam("", settings.getRotation());
rotationParam.setAdjustmentListener(this);
gbh.addControl(rotationParam.createGUI());

alignmentCB = new JComboBox<>(TextAlignment.values());
alignmentCB.setName("alignmentCB");
TextAlignment alignment = settings.getAlignment();
lastAlignment = alignment;
alignmentCB.setSelectedItem(alignment);

alignmentCB.addActionListener(e -> {
TextAlignment selectedAlignment = getSelectedAlignment();
if (selectedAlignment == TextAlignment.PATH && !comp.hasActivePath()) {
colorRotPanel.add(rotationParam.createGUI());
gbh.addControl(colorRotPanel);

boxAlignmentCB = new JComboBox<>(BoxAlignment.values());
boxAlignmentCB.setName("alignmentCB");
BoxAlignment alignment = settings.getAlignment();
lastBoxAlignment = alignment;
boxAlignmentCB.setSelectedItem(alignment);

boxAlignmentCB.addActionListener(e -> {
BoxAlignment selectedAlignment = getSelectedBoxAlignment();
if (selectedAlignment == BoxAlignment.PATH && !comp.hasActivePath()) {
String msg = "<html>There's no path in <b>\"" + comp.getName() + "\"</b>.<br>You can have text along a path after creating a path with the Pen Tool.";
Messages.showError("No Path", msg, this);
alignmentCB.setSelectedItem(lastAlignment);
boxAlignmentCB.setSelectedItem(lastBoxAlignment);
return;
}

lastAlignment = selectedAlignment;
lastBoxAlignment = selectedAlignment;
updateMLPAlignEnabled();
actionPerformed(e);
});
gbh.addLabel("Alignment:", 0, 2);
gbh.addControl(alignmentCB);
gbh.addLabel("Box Alignment:", 0, 2);

JPanel alignPanel = new JPanel(new FlowLayout(LEFT));
alignPanel.add(boxAlignmentCB);
mlpLabel = new JLabel(" Multiline/Path Alignment:");
alignPanel.add(mlpLabel);
mlpAlignmentSelector = new AlignmentSelector(settings.getMLPAlignment(), this);
alignPanel.add(mlpAlignmentSelector);
updateMLPAlignEnabled();

gbh.addControl(alignPanel);

return textPanel;
}
Expand All @@ -173,21 +190,35 @@ private void createTextArea(TextSettings settings) {
textArea.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
paramAdjusted();
textChanged();
}

@Override
public void removeUpdate(DocumentEvent e) {
paramAdjusted();
textChanged();
}

@Override
public void changedUpdate(DocumentEvent e) {
paramAdjusted();
textChanged();
}
});
}

private void textChanged() {
updateMLPAlignEnabled();
paramAdjusted();
}

private void updateMLPAlignEnabled() {
boolean hasMLPAlignNow = getSelectedBoxAlignment() == BoxAlignment.PATH || textArea.getText().contains("\n");
if (hasMLPAlignNow != hasMLPAlign) {
hasMLPAlign = hasMLPAlignNow;
mlpLabel.setEnabled(hasMLPAlign);
mlpAlignmentSelector.setEnabled(hasMLPAlign);
}
}

private JPanel createFontPanel(TextSettings settings) {
JPanel fontPanel = new JPanel(new GridBagLayout());
fontPanel.setBorder(createTitledBorder("Font"));
Expand Down Expand Up @@ -323,12 +354,12 @@ private void createEffectsPanel(TextSettings settings) {
}

private JPanel createBottomPanel(TextSettings settings) {
watermarkCB = new JCheckBox("Watermarking", settings.hasWatermark());
JPanel p = new JPanel(new FlowLayout(LEFT, 5, 5));

watermarkCB = new JCheckBox("Watermarking", settings.hasWatermark());
watermarkCB.addActionListener(this);

JPanel p = new JPanel(new FlowLayout(LEFT, 5, 5));
p.add(watermarkCB);

return p;
}

Expand All @@ -352,7 +383,7 @@ private TextSettings createSettingsFromGui() {
effects = effectsPanel.getEffects();
}

TextAlignment alignment = getSelectedAlignment();
BoxAlignment alignment = getSelectedBoxAlignment();

return new TextSettings(
textArea.getText(),
Expand All @@ -361,15 +392,16 @@ private TextSettings createSettingsFromGui() {
effects,
alignment.getHorizontal(),
alignment.getVertical(),
mlpAlignmentSelector.getSelectedAlignment(),
watermarkCB.isSelected(),
rotationParam.getValueInRadians(),
getRelLineHeight(),
getScaleX(), getScaleY(),
getShearX(), getShearY(), this);
}

private TextAlignment getSelectedAlignment() {
return (TextAlignment) alignmentCB.getSelectedItem();
private BoxAlignment getSelectedBoxAlignment() {
return (BoxAlignment) boxAlignmentCB.getSelectedItem();
}

private void updateApp(TextSettings settings) {
Expand Down Expand Up @@ -403,7 +435,9 @@ private void setUIValues(TextSettings settings) {
textArea.setText(settings.getText());
color.setColor(settings.getColor(), false);
rotationParam.setValue(settings.getRotation(), false);
alignmentCB.setSelectedItem(settings.getAlignment());
boxAlignmentCB.setSelectedItem(settings.getAlignment());
mlpAlignmentSelector.setSelected(settings.getMLPAlignment());
updateMLPAlignEnabled();

Font font = settings.getFont();
fontSizeSlider.setValue(font.getSize());
Expand Down
Loading

0 comments on commit 027d7f9

Please sign in to comment.