From d529d9867ff86f32b9d679fb532a24938e7adaff Mon Sep 17 00:00:00 2001 From: Erik Lumme Date: Wed, 13 Sep 2017 09:43:00 +0300 Subject: [PATCH] Migrate DynamicallyInjectingCSS --- .../articles/DynamicallyInjectingCSS.asciidoc | 307 ++++++++++++++++++ documentation/articles/contents.asciidoc | 1 + documentation/articles/img/theme-editor.png | Bin 0 -> 23869 bytes 3 files changed, 308 insertions(+) create mode 100644 documentation/articles/DynamicallyInjectingCSS.asciidoc create mode 100644 documentation/articles/img/theme-editor.png diff --git a/documentation/articles/DynamicallyInjectingCSS.asciidoc b/documentation/articles/DynamicallyInjectingCSS.asciidoc new file mode 100644 index 0000000000..d379ec6c4d --- /dev/null +++ b/documentation/articles/DynamicallyInjectingCSS.asciidoc @@ -0,0 +1,307 @@ +[[dynamically-injecting-css]] +Dynamically injecting CSS +------------------------- + +In most cases you will style your components using SASS or CSS and +create a theme for the application which you include with the `@Theme` +annotation. This is always the preferred way of theming your +application. But in some cases this is not enough. Sometimes you will +want your user to be able to change some property on-the-fly without +providing pre-made class names. To do this you can use CSS style +injection. In this example I am going to show you how you can use CSS +injection to create an editor which you can use to modify text visually +with, a WYSIWYG of sorts. Here is an image of the final component I am +going to create: + +image:img/theme-editor.png[Theme editor] + +First lets start by defining the UI of the editor component, it looks +like this: + +[source,java] +.... +private Component createEditor(String text) { + Panel editor = new Panel("Text Editor"); + editor.setWidth("580px"); + VerticalLayout panelContent = new VerticalLayout(); + panelContent.setSpacing(true); + panelContent.setMargin(new MarginInfo(true, false, false, false)); + editor.setContent(panelContent); + // Create the toolbar + HorizontalLayout toolbar = new HorizontalLayout(); + toolbar.setSpacing(true); + toolbar.setMargin(new MarginInfo(false, false, false, true)); + // Create the font family selector + toolbar.addComponent(createFontSelect()); + // Create the font size selector + toolbar.addComponent(createFontSizeSelect()); + // Create the text color selector + toolbar.addComponent(createTextColorSelect()); + // Create the background color selector + toolbar.addComponent(createBackgroundColorSelect()); + panelContent.addComponent(toolbar); + panelContent.setComponentAlignment(toolbar, Alignment.MIDDLE_LEFT); + // Spacer between toolbar and text + panelContent.addComponent(new Label("
", ContentMode.HTML)); + // The text to edit + TextArea textLabel = new TextArea(null, text); + textLabel.setWidth("100%"); + textLabel.setHeight("200px"); + // IMPORTANT: We are here setting the style name of the label, we are going to use this in our injected styles to target the label + textLabel.setStyleName("text-label"); + panelContent.addComponent(textLabel); + return editor; +} +.... + +Basically the editor component is a Panel with a text area and some +buttons which you can use to modify the text area text with. The +important thing here is that we give the text area a style name +"text-label". With this style name we will be able to inject CSS styles +targeted at that text area and modify colors and fonts of it. Lets next +take a look at how the controls in the toolbar is implemented. They are +all pretty similar but lets first take a look at how the Font selector +was made: + +[source,java] +.... +private Component createFontSelect() { + final ComboBox select = new ComboBox(null, + Arrays.asList("Arial", "Helvetica", "Verdana", "Courier", "Times", "sans-serif")); + select.setValue("Arial"); + select.setWidth("200px"); + select.setInputPrompt("Font"); + select.setDescription("Font"); + select.setImmediate(true); + select.setNullSelectionAllowed(false); + select.setNewItemsAllowed(false); + select.addValueChangeListener(new ValueChangeListener() { + @Override + public void valueChange( ValueChangeEvent event ) { + // Get the new font family + String fontFamily = select.getValue().toString(); + // Get the stylesheet of the page + Styles styles = Page.getCurrent().getStyles(); + // inject the new font size as a style. We need .v-app to override Vaadin's default styles here + styles.add(".v-app .v-textarea.text-label { font-family:" + fontFamily + "; }"); + } + }); + return select; +} +.... + +The important part here is what is inside the `ValueChangeListener`. Once +we get the value from the ComboBox we are ready to inject it to the page +so the user can visually see what have changed. To do this we fetch the +StyleSheet for the current Page by calling `Page.getCurrent()`. Once we +have the current Page we can get its StyleSheet by calling +`Page.getstyleSheet()`. Once we got the StyleSheet we are free to inject +any CSS string into the page by using `StyleSheet.inject(String css)`. As +you see here we use the style name we gave to the TextArea as the +selector and apply the font-family attribute to change the font family +to the one the user has selected. For the sake of clarity, lets look at +how another one, the text color selector, was implemented: + +[source,java] +.... +private Component createTextColorSelect( ) { + // Colorpicker for changing text color + ColorPicker textColor = new ColorPicker("Color", Color.BLACK); + textColor.setWidth("110px"); + textColor.setCaption("Color"); + textColor.addColorChangeListener(new ColorChangeListener() { + @Override + public void colorChanged( ColorChangeEvent event ) { + // Get the new text color + Color color = event.getColor(); + // Get the stylesheet of the page + Styles styles = Page.getCurrent().getStyles(); + // inject the new color as a style + styles.add(".v-app .v-textarea.text-label { color:" + color.getCSS() + "; }"); + } + }); + return textColor; +} +.... + +Again, the important part in this method is in the `ColorChangeListener`. +Basically here we do the exactly same thing as we did with the font +family except here we are dealing with a color. To change the color of +the text we just simply apply the 'color' attribute for text area. The +`ColorPicker.Color` even provides us with a convenient method of directly +converting the received Color object into a CSS color. And finally, for +completeness, here is the full example code which will produce the demo +application in the picture above for you to try out: + +[source,java] +.... +/** + * Imports and package definition omitted + */ +public class CSSInjectWithColorpicker extends UI { + @Override + protected void init( VaadinRequest request ) { // Create a text editor + Component editor = + createEditor("Lorem ipsum dolor sit amet, lacus pharetra sed, sit a " + + "tortor. Id aliquam lorem pede, orci ut enim metus, diam nulla mi " + + "suspendisse tempor tortor. Eleifend lorem proin, morbi vel diam ut. " + + "Tempor est tellus vitae, pretium condimentum facilisis sit. Sagittis " + + "quam, ac urna eros est cras id cras, eleifend eu mattis nec." + + "Lorem ipsum dolor sit amet, lacus pharetra sed, sit a " + + "tortor. Id aliquam lorem pede, orci ut enim metus, diam nulla mi " + + "suspendisse tempor tortor. Eleifend lorem proin, morbi vel diam ut. " + + "Tempor est tellus vitae, pretium condimentum facilisis sit. Sagittis " + + "quam, ac urna eros est cras id cras, eleifend eu mattis nec." + + "Lorem ipsum dolor sit amet, lacus pharetra sed, sit a " + + "tortor. Id aliquam lorem pede, orci ut enim metus, diam nulla mi " + + "suspendisse tempor tortor. Eleifend lorem proin, morbi vel diam ut. " + + "Tempor est tellus vitae, pretium condimentum facilisis sit. Sagittis " + + "quam, ac urna eros est cras id cras, eleifend eu mattis nec." + + "Lorem ipsum dolor sit amet, lacus pharetra sed, sit a " + + "tortor. Id aliquam lorem pede, orci ut enim metus, diam nulla mi " + + "suspendisse tempor tortor. Eleifend lorem proin, morbi vel diam ut. " + + "Tempor est tellus vitae, pretium condimentum facilisis sit. Sagittis " + + "quam, ac urna eros est cras id cras, eleifend eu mattis nec."); + VerticalLayout content = new VerticalLayout(editor); + content.setMargin(true); + setContent(content); + } + + /** + * Creates a text editor for visually editing text + * + * @param text The text editor + * @return + */ + private Component createEditor( String text ) { + Panel editor = new Panel("Text Editor"); + editor.setWidth("580px"); + VerticalLayout panelContent = new VerticalLayout(); + panelContent.setSpacing(true); + panelContent.setMargin(new MarginInfo(true, false, false, false)); + editor.setContent(panelContent); + // Create the toolbar + HorizontalLayout toolbar = new HorizontalLayout(); + toolbar.setSpacing(true); + toolbar.setMargin(new MarginInfo(false, false, false, true)); + // Create the font family selector + toolbar.addComponent(createFontSelect()); + // Create the font size selector + toolbar.addComponent(createFontSizeSelect()); + // Create the text color selector + toolbar.addComponent(createTextColorSelect()); + // Create the background color selector + toolbar.addComponent(createBackgroundColorSelect()); + panelContent.addComponent(toolbar); + panelContent.setComponentAlignment(toolbar, Alignment.MIDDLE_LEFT); + // Spacer between toolbar and text + panelContent.addComponent(new Label("
", ContentMode.HTML)); + // The text to edit + TextArea textLabel = new TextArea(null, text); + textLabel.setWidth("100%"); + textLabel.setHeight("200px"); + // IMPORTANT: We are here setting the style name of the label, we are going to use this in our injected styles to + // target the label + textLabel.setStyleName("text-label"); + panelContent.addComponent(textLabel); + return editor; + } + + /** + * Creates a background color select dialog + */ + private Component createBackgroundColorSelect( ) { + ColorPicker bgColor = new ColorPicker("Background", Color.WHITE); + bgColor.setWidth("110px"); + bgColor.setCaption("Background"); + bgColor.addColorChangeListener(new ColorChangeListener() { + @Override + public void colorChanged( ColorChangeEvent event ) { + // Get the new background color + Color color = event.getColor(); + // Get the stylesheet of the page + Styles styles = Page.getCurrent().getStyles(); + // inject the new background color + styles.add(".v-app .v-textarea.text-label { background-color:" + color.getCSS() + "; }"); + } + }); + return bgColor; + } + + /** + * Create a text color selection dialog + */ + private Component createTextColorSelect( ) { + // Colorpicker for changing text color + ColorPicker textColor = new ColorPicker("Color", Color.BLACK); + textColor.setWidth("110px"); + textColor.setCaption("Color"); + textColor.addColorChangeListener(new ColorChangeListener() { + + @Override + public void colorChanged( ColorChangeEvent event ) { + // Get the new text color + Color color = event.getColor(); + // Get the stylesheet of the page + Styles styles = Page.getCurrent().getStyles(); + // inject the new color as a style + styles.add(".v-app .v-textarea.text-label { color:" + color.getCSS() + "; }"); + } + }); + return textColor; + } + + /** + * Creates a font family selection dialog + */ + private Component createFontSelect( ) { + final ComboBox select = + new ComboBox(null, Arrays.asList("Arial", "Helvetica", "Verdana", "Courier", "Times", "sans-serif")); + select.setValue("Arial"); + select.setWidth("200px"); + select.setInputPrompt("Font"); + select.setDescription("Font"); + select.setImmediate(true); + select.setNullSelectionAllowed(false); + select.setNewItemsAllowed(false); + select.addValueChangeListener(new ValueChangeListener() { + @Override + public void valueChange( ValueChangeEvent event ) { + // Get the new font family + String fontFamily = select.getValue().toString(); + // Get the stylesheet of the page + Styles styles = Page.getCurrent().getStyles(); + // inject the new font size as a style. We need .v-app to override Vaadin's default styles here + styles.add(".v-app .v-textarea.text-label { font-family:" + fontFamily + "; }"); + } + }); + return select; + } + + /** + * Creates a font size selection control + */ + private Component createFontSizeSelect( ) { + final ComboBox select = new ComboBox(null, Arrays.asList(8, 9, 10, 12, 14, 16, 20, 25, 30, 40, 50)); + select.setWidth("100px"); + select.setValue(12); + select.setInputPrompt("Font size"); + select.setDescription("Font size"); + select.setImmediate(true); + select.setNullSelectionAllowed(false); + select.setNewItemsAllowed(false); + select.addValueChangeListener(new ValueChangeListener() { + @Override + public void valueChange( ValueChangeEvent event ) { + // Get the new font size + Integer fontSize = (Integer) select.getValue(); + // Get the stylesheet of the page + Styles styles = Page.getCurrent().getStyles(); + // inject the new font size as a style. We need .v-app to override Vaadin's default styles here + styles.add(".v-app .v-textarea.text-label { font-size:" + String.valueOf(fontSize) + "px; }"); + } + }); + return select; + } +} +.... diff --git a/documentation/articles/contents.asciidoc b/documentation/articles/contents.asciidoc index 396e4dfc3b..60a555f848 100644 --- a/documentation/articles/contents.asciidoc +++ b/documentation/articles/contents.asciidoc @@ -60,4 +60,5 @@ are great, too. - link:LoadTestingWithGatling.asciidoc[Load testing with Gatling] - link:VaadinScalabilityTestingWithAmazonWebServices.asciidoc[Vaadin scalability testing with Amazon Web Services] - link:UsingFontIcons.asciidoc[Using font icons in Vaadin 7.2] +- link:DynamicallyInjectingCSS.asciidoc[Dynamically injecting CSS] - link:CreatingAUIExtension.asciidoc[Creating a UI extension] diff --git a/documentation/articles/img/theme-editor.png b/documentation/articles/img/theme-editor.png new file mode 100644 index 0000000000000000000000000000000000000000..6785823d4e4ffbfbad77504604f1e41465eb6386 GIT binary patch literal 23869 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