SEBSERV-58 implemented
This commit is contained in:
parent
e3b0d2251e
commit
3e8b52acb9
8 changed files with 113 additions and 85 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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("<span style='padding: 2px 5px 2px 5px; background-color: #")
|
||||
.append(threshold.color)
|
||||
.append(Constants.EMBEDDED_LIST_SEPARATOR),
|
||||
.append("; ")
|
||||
.append((Utils.darkColor(Utils.parseRGB(threshold.color)))
|
||||
? "color: #4a4a4a; "
|
||||
: "color: #FFFFFF;")
|
||||
.append("'>")
|
||||
.append(threshold.value).append(" (").append(threshold.color).append(")")
|
||||
.append("</span>")
|
||||
.append(" | "),
|
||||
(sb1, sb2) -> sb1.append(sb2))
|
||||
.toString();
|
||||
}
|
||||
|
|
|
@ -154,6 +154,7 @@ public class EntityTable<ROW extends Entity> {
|
|||
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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
|
||||
;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue