123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 |
- ---
- title: Dynamically Injecting CSS
- order: 54
- layout: page
- ---
-
- [[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("<hr />", 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("<hr />", 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;
- }
- }
- ....
|