diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/util/Utils.java b/src/main/java/ch/ethz/seb/sebserver/gbl/util/Utils.java index ae402f4e..24bec221 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/util/Utils.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/util/Utils.java @@ -44,6 +44,7 @@ import ch.ethz.seb.sebserver.gbl.Constants; public final class Utils { + public static final int DARK_COLOR_THRESHOLD = 400; public static final Predicate TRUE_PREDICATE = v -> true; public static final Predicate FALSE_PREDICATE = v -> false; public static final Runnable EMPTY_EXECUTION = () -> { @@ -414,4 +415,35 @@ public final class Utils { } return e.getCause().getClass().getName() + " : " + e.getCause().getMessage(); } + + public static boolean darkColor(final RGB rgb) { + return rgb.red + rgb.green + rgb.blue > DARK_COLOR_THRESHOLD; + } + + public static String parseColorString(final RGB color) { + if (color == null) { + return null; + } + + return toColorFractionString(color.red) + + toColorFractionString(color.green) + + toColorFractionString(color.blue); + } + + public static RGB parseRGB(final String colorString) { + if (StringUtils.isBlank(colorString)) { + return null; + } + + final int r = Integer.parseInt(colorString.substring(0, 2), 16); + final int g = Integer.parseInt(colorString.substring(2, 4), 16); + final int b = Integer.parseInt(colorString.substring(4, 6), 16); + + return new RGB(r, g, b); + } + + public static String toColorFractionString(final int fraction) { + final String hexString = Integer.toHexString(fraction); + return (hexString.length() < 2) ? "0" + hexString : hexString; + } } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamForm.java index 784cff24..e469670b 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamForm.java @@ -46,6 +46,7 @@ import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult; import ch.ethz.seb.sebserver.gbl.model.user.UserRole; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import ch.ethz.seb.sebserver.gbl.util.Result; +import ch.ethz.seb.sebserver.gbl.util.Utils; import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition; import ch.ethz.seb.sebserver.gui.form.FormBuilder; import ch.ethz.seb.sebserver.gui.form.FormHandle; @@ -266,9 +267,9 @@ public class ExamForm implements TemplateComposer { exam.externalId) .addField(FormBuilder.text( - Domain.EXAM.ATTR_EXTERNAL_ID, - FORM_QUIZID_TEXT_KEY, - exam.externalId) + QuizData.QUIZ_ATTR_NAME, + FORM_NAME_TEXT_KEY, + exam.name) .readonly(true) .withInputSpan(3) .withEmptyCellSeparation(false)) @@ -298,19 +299,16 @@ public class ExamForm implements TemplateComposer { .withEmptyCellSeparation(false)) .addField(FormBuilder.text( - QuizData.QUIZ_ATTR_NAME, - FORM_NAME_TEXT_KEY, - exam.name) + Domain.EXAM.ATTR_EXTERNAL_ID, + FORM_QUIZID_TEXT_KEY, + exam.externalId) .readonly(true) - .withInputSpan(3) .withEmptyCellSeparation(false)) .addField(FormBuilder.text( QuizData.QUIZ_ATTR_START_URL, FORM_QUIZ_URL_TEXT_KEY, exam.startURL) - .readonly(true) - .withInputSpan(3) - .withEmptyCellSeparation(false)) + .readonly(true)) .addField(FormBuilder.text( QuizData.QUIZ_ATTR_DESCRIPTION, @@ -318,8 +316,7 @@ public class ExamForm implements TemplateComposer { exam.description) .asArea() .readonly(true) - .withInputSpan(6) - .withEmptyCellSeparation(false)) + .withInputSpan(6)) .addField(FormBuilder.text( Domain.EXAM.ATTR_STATUS + "_display", @@ -718,7 +715,6 @@ public class ExamForm implements TemplateComposer { .getText(ResourceService.EXAM_INDICATOR_TYPE_PREFIX + indicator.type.name()); } - // TODO find a better way to show a threshold value as text private static String thresholdsValue(final Indicator indicator) { if (indicator.thresholds.isEmpty()) { return Constants.EMPTY_NOTE; @@ -728,10 +724,17 @@ public class ExamForm implements TemplateComposer { .stream() .reduce( new StringBuilder(), - (sb, threshold) -> sb.append(threshold.value) - .append(Constants.URL_PORT_SEPARATOR) + (sb, threshold) -> sb + .append("") + .append(threshold.value).append(" (").append(threshold.color).append(")") + .append("") + .append(" | "), (sb1, sb2) -> sb1.append(sb2)) .toString(); } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/table/EntityTable.java b/src/main/java/ch/ethz/seb/sebserver/gui/table/EntityTable.java index 34d2b7cd..1a665bea 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/table/EntityTable.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/table/EntityTable.java @@ -154,6 +154,7 @@ public class EntityTable { this.table.setHeaderVisible(true); this.table.setLinesVisible(true); this.table.setData(RWT.CUSTOM_ITEM_HEIGHT, ROW_HEIGHT); + this.table.setData(RWT.MARKUP_ENABLED, Boolean.TRUE); if (defaultActionFunction != null) { final PageAction defaultAction = defaultActionFunction.apply(this); diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/widget/ColorSelection.java b/src/main/java/ch/ethz/seb/sebserver/gui/widget/ColorSelection.java index ea90386b..a5231588 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/widget/ColorSelection.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/widget/ColorSelection.java @@ -11,6 +11,7 @@ package ch.ethz.seb.sebserver.gui.widget; import java.util.List; import org.apache.commons.lang3.StringUtils; +import org.eclipse.rap.rwt.RWT; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.RGB; @@ -25,7 +26,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ch.ethz.seb.sebserver.gbl.util.Tuple; +import ch.ethz.seb.sebserver.gbl.util.Utils; import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey; +import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.CustomVariant; import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.ImageIcon; public final class ColorSelection extends Composite implements Selection { @@ -36,8 +39,10 @@ public final class ColorSelection extends Composite implements Selection { private static final LocTextKey DEFAULT_SELECT_TOOLTIP_KEY = new LocTextKey("sebserver.overall.action.select"); private static final int ACTION_COLUMN_WIDTH = 20; + private static final int ACTION_COLUMN_ADJUST = 10; private final ColorDialog colorDialog; private final Composite colorField; + private final Label colorLabel; private RGB selection; private Listener listener = null; @@ -62,6 +67,15 @@ public final class ColorSelection extends Composite implements Selection { final GridData colorCell = new GridData(SWT.FILL, SWT.TOP, true, false); colorCell.heightHint = 20; this.colorField.setLayoutData(colorCell); + final GridLayout colorCallLayout = new GridLayout(); + colorCallLayout.horizontalSpacing = 5; + colorCallLayout.verticalSpacing = 0; + colorCallLayout.marginHeight = 0; + colorCallLayout.marginTop = 2; + this.colorField.setLayout(colorCallLayout); + this.colorLabel = new Label(this.colorField, SWT.NONE); + this.colorLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, true, false)); + this.colorLabel.setData(RWT.CUSTOM_VARIANT, CustomVariant.LIGHT_COLOR_LABEL.key); final Label imageButton = widgetFactory.imageButton( ImageIcon.COLOR, @@ -94,13 +108,13 @@ public final class ColorSelection extends Composite implements Selection { @Override public void select(final String keys) { - this.selection = parseRGB(keys); + this.selection = Utils.parseRGB(keys); applySelection(); } @Override public String getSelectionValue() { - return parseColorString(this.selection); + return Utils.parseColorString(this.selection); } @Override @@ -125,47 +139,27 @@ public final class ColorSelection extends Composite implements Selection { private void applySelection() { if (this.selection != null) { this.colorField.setBackground(new Color(this.getDisplay(), this.selection)); + this.colorLabel.setText(Utils.parseColorString(this.selection)); + this.colorLabel.setData(RWT.CUSTOM_VARIANT, (Utils.darkColor(this.selection)) + ? CustomVariant.DARK_COLOR_LABEL.key + : CustomVariant.LIGHT_COLOR_LABEL.key); } else { this.colorField.setBackground(null); + this.colorLabel.setText(StringUtils.EMPTY); } + + this.colorField.layout(true, true); } private void adaptColumnWidth(final Event event) { try { final int currentTableWidth = this.getClientArea().width; final GridData comboCell = (GridData) this.colorField.getLayoutData(); - comboCell.widthHint = currentTableWidth - ACTION_COLUMN_WIDTH; + comboCell.widthHint = currentTableWidth - ACTION_COLUMN_WIDTH - ACTION_COLUMN_ADJUST; this.layout(); } catch (final Exception e) { log.warn("Failed to adaptColumnWidth: ", e); } } - static String parseColorString(final RGB color) { - if (color == null) { - return null; - } - - return toColorFractionString(color.red) - + toColorFractionString(color.green) - + toColorFractionString(color.blue); - } - - static RGB parseRGB(final String colorString) { - if (StringUtils.isBlank(colorString)) { - return null; - } - - final int r = Integer.parseInt(colorString.substring(0, 2), 16); - final int g = Integer.parseInt(colorString.substring(2, 4), 16); - final int b = Integer.parseInt(colorString.substring(4, 6), 16); - - return new RGB(r, g, b); - } - - static String toColorFractionString(final int fraction) { - final String hexString = Integer.toHexString(fraction); - return (hexString.length() < 2) ? "0" + hexString : hexString; - } - } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/widget/WidgetFactory.java b/src/main/java/ch/ethz/seb/sebserver/gui/widget/WidgetFactory.java index 934590d9..065830b9 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/widget/WidgetFactory.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/widget/WidgetFactory.java @@ -140,7 +140,10 @@ public class WidgetFactory { MESSAGE("message"), ERROR("error"), WARNING("warning"), - CONFIG_INPUT_READONLY("inputreadonly") + CONFIG_INPUT_READONLY("inputreadonly"), + + DARK_COLOR_LABEL("colordark"), + LIGHT_COLOR_LABEL("colorlight") ; diff --git a/src/main/resources/static/css/sebserver.css b/src/main/resources/static/css/sebserver.css index 41358a83..930d6f19 100644 --- a/src/main/resources/static/css/sebserver.css +++ b/src/main/resources/static/css/sebserver.css @@ -108,6 +108,18 @@ Label-SeparatorLine { height: 1px; } +Label.colordark { + font: 12px Arial, Helvetica, monospace; + letter-spacing: 3.25px; + color: #4a4a4a; +} + +Label.colorlight { + font: 12px Arial, Helvetica, monospace; + letter-spacing: 3.25px; + color: #FFFFFF; +} + Composite.bordered { border: 2px; } diff --git a/src/test/java/ch/ethz/seb/sebserver/gbl/util/UtilsTest.java b/src/test/java/ch/ethz/seb/sebserver/gbl/util/UtilsTest.java index c7fe27b2..3aad984c 100644 --- a/src/test/java/ch/ethz/seb/sebserver/gbl/util/UtilsTest.java +++ b/src/test/java/ch/ethz/seb/sebserver/gbl/util/UtilsTest.java @@ -13,6 +13,7 @@ import static org.junit.Assert.assertEquals; import java.util.Collection; import java.util.Set; +import org.eclipse.swt.graphics.RGB; import org.junit.Test; public class UtilsTest { @@ -45,4 +46,24 @@ public class UtilsTest { assertEquals("[ONE, TWO]", r5.toString()); } + @Test + public void testParseRGB() { + String colorString = "FFFFFF"; + assertEquals( + "RGB {255, 255, 255}", + Utils.parseRGB(colorString).toString()); + + colorString = "FFaa34"; + assertEquals( + "RGB {255, 170, 52}", + Utils.parseRGB(colorString).toString()); + } + + @Test + public void testParseColorString() { + final RGB color = new RGB(255, 255, 255); + assertEquals("ffffff", Utils.parseColorString(color)); + + } + } diff --git a/src/test/java/ch/ethz/seb/sebserver/gui/widget/ColorSelectionTest.java b/src/test/java/ch/ethz/seb/sebserver/gui/widget/ColorSelectionTest.java deleted file mode 100644 index 495eb9da..00000000 --- a/src/test/java/ch/ethz/seb/sebserver/gui/widget/ColorSelectionTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET) - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -package ch.ethz.seb.sebserver.gui.widget; - -import static org.junit.Assert.assertEquals; - -import org.eclipse.swt.graphics.RGB; -import org.junit.Test; - -public class ColorSelectionTest { - - @Test - public void testParseRGB() { - String colorString = "FFFFFF"; - assertEquals( - "RGB {255, 255, 255}", - ColorSelection.parseRGB(colorString).toString()); - - colorString = "FFaa34"; - assertEquals( - "RGB {255, 170, 52}", - ColorSelection.parseRGB(colorString).toString()); - } - - @Test - public void testParseColorString() { - final RGB color = new RGB(255, 255, 255); - assertEquals("ffffff", ColorSelection.parseColorString(color)); - - } - -}