<commit_before>/*******************************************************************************
 * Copyright (c) 2015-2016 Oak Ridge National Laboratory.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/
package org.csstudio.display.builder.model.widgets;

import static org.csstudio.display.builder.model.ModelPlugin.logger;
import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propFile;
import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propMacros;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.logging.Level;

import org.csstudio.display.builder.model.DisplayModel;
import org.csstudio.display.builder.model.Messages;
import org.csstudio.display.builder.model.RuntimeWidgetProperty;
import org.csstudio.display.builder.model.Widget;
import org.csstudio.display.builder.model.WidgetCategory;
import org.csstudio.display.builder.model.WidgetConfigurator;
import org.csstudio.display.builder.model.WidgetDescriptor;
import org.csstudio.display.builder.model.WidgetProperty;
import org.csstudio.display.builder.model.WidgetPropertyCategory;
import org.csstudio.display.builder.model.WidgetPropertyDescriptor;
import org.csstudio.display.builder.model.macros.Macros;
import org.csstudio.display.builder.model.persist.ModelReader;
import org.csstudio.display.builder.model.persist.XMLTags;
import org.csstudio.display.builder.model.persist.XMLUtil;
import org.csstudio.display.builder.model.properties.CommonWidgetProperties;
import org.csstudio.display.builder.model.properties.EnumWidgetProperty;
import org.csstudio.display.builder.model.widgets.GroupWidget.Style;
import org.osgi.framework.Version;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/** Widget that shows another display inside itself
 *  @author <NAME>
 */
@SuppressWarnings("nls")
public class EmbeddedDisplayWidget extends VisibleWidget
{
    /** Widget descriptor */
    public static final WidgetDescriptor WIDGET_DESCRIPTOR =
        new WidgetDescriptor("embedded", WidgetCategory.STRUCTURE,
            "Embedded Display",
            "platform:/plugin/org.csstudio.display.builder.model/icons/embedded.png",
            "Widget that embeds another display",
            Arrays.asList("org.csstudio.opibuilder.widgets.linkingContainer"))
    {
        @Override
        public Widget createWidget()
        {
            return new EmbeddedDisplayWidget();
        }
    };

    /** Reserved widget user data key for representation container.
     *
     *  <p>The representation of the {@link EmbeddedDisplayWidget} sets this
     *  to the toolkit-specific container item which becomes the 'parent'
     *  of the representations for the embedded content.
     *
     *  <p>The embedded widget runtime later reads this whenever it needs
     *  to create a toolkit representation for the embedded model.
     */
    public static final String USER_DATA_EMBEDDED_DISPLAY_CONTAINER = "_embedded_widget_container";

    /** Resize behavior */
    public enum Resize
    {
        /** No resize, add scroll bars if content too large for container */
        None(Messages.Resize_None),

        /** Size *.opi to fit the container */
        ResizeContent(Messages.Resize_Content),

        /** Size the container to fit the linked *.opi */
        SizeToContent(Messages.Resize_Container);

        private final String label;

        private Resize(final String label)
        {
            this.label = label;
        }

        @Override
        public String toString()
        {
            return label;
        }
    }

    private static final WidgetPropertyDescriptor<Resize> propResize =
        new WidgetPropertyDescriptor<Resize>(
            WidgetPropertyCategory.DISPLAY, "resize", Messages.WidgetProperties_ResizeBehavior)
    {
        @Override
        public EnumWidgetProperty<Resize> createProperty(final Widget widget,
                                                         final Resize default_value)
        {
            return new EnumWidgetProperty<Resize>(this, widget, default_value);
        }
    };

    private static final WidgetPropertyDescriptor<String> propGroupName =
        CommonWidgetProperties.newStringPropertyDescriptor(
            WidgetPropertyCategory.DISPLAY, "group_name", Messages.EmbeddedDisplayWidget_GroupName);

    private static final WidgetPropertyDescriptor<DisplayModel> runtimeModel =
        new WidgetPropertyDescriptor<DisplayModel>(WidgetPropertyCategory.RUNTIME, "embedded_model", "Embedded Model")
        {
            @Override
            public WidgetProperty<DisplayModel> createProperty(final Widget widget, DisplayModel default_value)
            {
                return new RuntimeWidgetProperty<DisplayModel>(runtimeModel, widget, default_value)
                {
                    @Override
                    public void setValueFromObject(final Object value)
                            throws Exception
                    {
                        if (! (value instanceof DisplayModel))
                            throw new IllegalArgumentException("Expected DisplayModel, got " + Objects.toString(value));
                        doSetValue((DisplayModel)value, true);
                    }
                };
            }
        };

    /** Custom configurator to read legacy *.opi files */
    private static class EmbeddedDisplayWidgetConfigurator extends WidgetConfigurator
    {
        public EmbeddedDisplayWidgetConfigurator(final Version xml_version)
        {
            super(xml_version);
        }

        @Override
        public boolean configureFromXML(final ModelReader model_reader, final Widget widget, final Element xml)
                throws Exception
        {
            if (! super.configureFromXML(model_reader, widget, xml))
                return false;

            if (xml_version.getMajor() < 2)
            {
                // Fall back to legacy "opi_file" for display file
                if (XMLUtil.getChildElement(xml, propFile.getName()) == null)
                {
                    final Optional<String> opi_file = XMLUtil.getChildString(xml, "opi_file");
                    if (opi_file.isPresent())
                        widget.setPropertyValue(propFile, opi_file.get());
                }

                // Transition legacy "resize_behaviour"
                Element element = XMLUtil.getChildElement(xml, "resize_behaviour");
                if (element != null)
                {
                    try
                    {   // 0=SIZE_OPI_TO_CONTAINER, 1=SIZE_CONTAINER_TO_OPI, 2=CROP_OPI, 3=SCROLL_OPI
                        final int old_resize = Integer.parseInt(XMLUtil.getString(element));
                        if (old_resize == 0)
                            widget.setPropertyValue(propResize, Resize.ResizeContent);
                        else if (old_resize == 1)
                            widget.setPropertyValue(propResize, Resize.SizeToContent);
                        else
                            widget.setPropertyValue(propResize, Resize.None);
                    }
                    catch (NumberFormatException ex)
                    {
                        logger.log(Level.WARNING, "Cannot decode legacy resize_behavior");
                    }
                }

                // Transition legacy border
                final int border_style = XMLUtil.getChildInteger(xml, "border_style").orElse(0);
                final int border_width = XMLUtil.getChildInteger(xml, "border_width").orElse(0);
                final Style style = GroupWidget.convertLegacyStyle(border_style);

                // TODO Only if line with width > ..
                if (style != Style.NONE)
                {<commit_msg>Embedded display: Tweak transition of legacy border<commit_after>/*******************************************************************************
 * Copyright (c) 2015-2016 Oak Ridge National Laboratory.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/
package org.csstudio.display.builder.model.widgets;

import static org.csstudio.display.builder.model.ModelPlugin.logger;
import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propFile;
import static org.csstudio.display.builder.model.properties.CommonWidgetProperties.propMacros;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.logging.Level;

import org.csstudio.display.builder.model.DisplayModel;
import org.csstudio.display.builder.model.Messages;
import org.csstudio.display.builder.model.RuntimeWidgetProperty;
import org.csstudio.display.builder.model.Widget;
import org.csstudio.display.builder.model.WidgetCategory;
import org.csstudio.display.builder.model.WidgetConfigurator;
import org.csstudio.display.builder.model.WidgetDescriptor;
import org.csstudio.display.builder.model.WidgetProperty;
import org.csstudio.display.builder.model.WidgetPropertyCategory;
import org.csstudio.display.builder.model.WidgetPropertyDescriptor;
import org.csstudio.display.builder.model.macros.Macros;
import org.csstudio.display.builder.model.persist.ModelReader;
import org.csstudio.display.builder.model.persist.XMLTags;
import org.csstudio.display.builder.model.persist.XMLUtil;
import org.csstudio.display.builder.model.properties.CommonWidgetProperties;
import org.csstudio.display.builder.model.properties.EnumWidgetProperty;
import org.csstudio.display.builder.model.widgets.GroupWidget.Style;
import org.osgi.framework.Version;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/** Widget that shows another display inside itself
 *  @author <NAME>
 */
@SuppressWarnings("nls")
public class EmbeddedDisplayWidget extends VisibleWidget
{
    /** Widget descriptor */
    public static final WidgetDescriptor WIDGET_DESCRIPTOR =
        new WidgetDescriptor("embedded", WidgetCategory.STRUCTURE,
            "Embedded Display",
            "platform:/plugin/org.csstudio.display.builder.model/icons/embedded.png",
            "Widget that embeds another display",
            Arrays.asList("org.csstudio.opibuilder.widgets.linkingContainer"))
    {
        @Override
        public Widget createWidget()
        {
            return new EmbeddedDisplayWidget();
        }
    };

    /** Reserved widget user data key for representation container.
     *
     *  <p>The representation of the {@link EmbeddedDisplayWidget} sets this
     *  to the toolkit-specific container item which becomes the 'parent'
     *  of the representations for the embedded content.
     *
     *  <p>The embedded widget runtime later reads this whenever it needs
     *  to create a toolkit representation for the embedded model.
     */
    public static final String USER_DATA_EMBEDDED_DISPLAY_CONTAINER = "_embedded_widget_container";

    /** Resize behavior */
    public enum Resize
    {
        /** No resize, add scroll bars if content too large for container */
        None(Messages.Resize_None),

        /** Size *.opi to fit the container */
        ResizeContent(Messages.Resize_Content),

        /** Size the container to fit the linked *.opi */
        SizeToContent(Messages.Resize_Container);

        private final String label;

        private Resize(final String label)
        {
            this.label = label;
        }

        @Override
        public String toString()
        {
            return label;
        }
    }

    private static final WidgetPropertyDescriptor<Resize> propResize =
        new WidgetPropertyDescriptor<Resize>(
            WidgetPropertyCategory.DISPLAY, "resize", Messages.WidgetProperties_ResizeBehavior)
    {
        @Override
        public EnumWidgetProperty<Resize> createProperty(final Widget widget,
                                                         final Resize default_value)
        {
            return new EnumWidgetProperty<Resize>(this, widget, default_value);
        }
    };

    private static final WidgetPropertyDescriptor<String> propGroupName =
        CommonWidgetProperties.newStringPropertyDescriptor(
            WidgetPropertyCategory.DISPLAY, "group_name", Messages.EmbeddedDisplayWidget_GroupName);

    private static final WidgetPropertyDescriptor<DisplayModel> runtimeModel =
        new WidgetPropertyDescriptor<DisplayModel>(WidgetPropertyCategory.RUNTIME, "embedded_model", "Embedded Model")
        {
            @Override
            public WidgetProperty<DisplayModel> createProperty(final Widget widget, DisplayModel default_value)
            {
                return new RuntimeWidgetProperty<DisplayModel>(runtimeModel, widget, default_value)
                {
                    @Override
                    public void setValueFromObject(final Object value)
                            throws Exception
                    {
                        if (! (value instanceof DisplayModel))
                            throw new IllegalArgumentException("Expected DisplayModel, got " + Objects.toString(value));
                        doSetValue((DisplayModel)value, true);
                    }
                };
            }
        };

    /** Custom configurator to read legacy *.opi files */
    private static class EmbeddedDisplayWidgetConfigurator extends WidgetConfigurator
    {
        public EmbeddedDisplayWidgetConfigurator(final Version xml_version)
        {
            super(xml_version);
        }

        @Override
        public boolean configureFromXML(final ModelReader model_reader, final Widget widget, final Element xml)
                throws Exception
        {
            if (! super.configureFromXML(model_reader, widget, xml))
                return false;

            if (xml_version.getMajor() < 2)
            {
                // Fall back to legacy "opi_file" for display file
                if (XMLUtil.getChildElement(xml, propFile.getName()) == null)
                {
                    final Optional<String> opi_file = XMLUtil.getChildString(xml, "opi_file");
                    if (opi_file.isPresent())
                        widget.setPropertyValue(propFile, opi_file.get());
                }

                // Transition legacy "resize_behaviour"
                Element element = XMLUtil.getChildElement(xml, "resize_behaviour");
                if (element != null)
                {
                    try
                    {   // 0=SIZE_OPI_TO_CONTAINER, 1=SIZE_CONTAINER_TO_OPI, 2=CROP_OPI, 3=SCROLL_OPI
                        final int old_resize = Integer.parseInt(XMLUtil.getString(element));
                        if (old_resize == 0)
                            widget.setPropertyValue(propResize, Resize.ResizeContent);
                        else if (old_resize == 1)
                            widget.setPropertyValue(propResize, Resize.SizeToContent);
                        else
                            widget.setPropertyValue(propResize, Resize.None);
                    }
                    catch (NumberFormatException ex)
                    {
                        logger.log(Level.WARNING, "Cannot decode legacy resize_behavior");
                    }
                }

                // Transition legacy border if it was an explicit line
                // or a style that includes a label
                final int border_style = XMLUtil.getChildInteger(xml, "border_style").orElse(0);
                if (border_style == 1  || // LINE
                    border_style == 12 || // TITLE_BAR
                    border_style == 13)   // GROUP_BOX
                {
                    final Style style = GroupWidget.convertLegacyStyle(border_style);
{'fraction_non_alphanumeric': 0.0979851797415641, 'fraction_numerical': 0.003184518341600833, 'mean_word_length': 2.380252535706893, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 30, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 19}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6278230', 'n_tokens_mistral': 4121, 'n_tokens_neox': 3962, 'n_words': 923}