<commit_before>/*
 * Copyright (c) 2008-2013 Haulmont. All rights reserved.
 * Use is subject to license terms, see http://www.cuba-platform.com/license for details.
 */

package com.haulmont.cuba.desktop.gui.components;

import com.haulmont.chile.core.datatypes.Datatypes;
import com.haulmont.chile.core.model.MetaClass;
import com.haulmont.chile.core.model.MetaProperty;
import com.haulmont.chile.core.model.MetaPropertyPath;
import com.haulmont.chile.core.model.utils.InstanceUtils;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.global.*;
import com.haulmont.cuba.desktop.sys.DesktopToolTipManager;
import com.haulmont.cuba.desktop.sys.vcl.Flushable;
import com.haulmont.cuba.gui.AppConfig;
import com.haulmont.cuba.gui.components.DateField;
import com.haulmont.cuba.gui.components.IFrame;
import com.haulmont.cuba.gui.components.TimeField;
import com.haulmont.cuba.gui.data.Datasource;
import com.haulmont.cuba.gui.data.impl.DsListenerAdapter;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;

import javax.swing.*;
import javax.swing.text.MaskFormatter;
import java.awt.*;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import static com.haulmont.bali.util.Preconditions.checkNotNullArgument;

/**
 * @author krivopustov
 * @version $Id$
 */
public class DesktopTimeField extends DesktopAbstractField<JFormattedTextField> implements TimeField {

    private boolean showSeconds;
    private String timeFormat;
    private String mask;
    private MaskFormatter formatter;
    private boolean updatingInstance;
    private Datasource datasource;
    private MetaProperty metaProperty;
    private MetaPropertyPath metaPropertyPath;
    private Object prevValue;
    private String caption;
    private DateField.Resolution resolution;
    private boolean editable = true;

    protected static final int DIGIT_WIDTH = 23;

    public DesktopTimeField() {
        UserSessionSource uss = AppBeans.get(UserSessionSource.NAME);

        timeFormat = Datatypes.getFormatStrings(uss.getLocale()).getTimeFormat();
        resolution = DateField.Resolution.MIN;
        formatter = new MaskFormatter();
        formatter.setPlaceholderCharacter('_');
        impl = new FlushableFormattedTextField(formatter);
        FieldListener listener = new FieldListener();
        impl.addFocusListener(listener);
        impl.addKeyListener(listener);

        setShowSeconds(timeFormat.contains("ss"));
    }

    @Override
    public boolean getShowSeconds() {
        return showSeconds;
    }

    private Object validateRawValue(String value) throws NumberFormatException, ParseException {
        if (value.equals(StringUtils.replaceChars(mask, "#U", "__")))
            return null;

        SimpleDateFormat sdf = new SimpleDateFormat(timeFormat);
        sdf.setLenient(false);
        try {
            return sdf.parse(value);
        } catch (ParseException e) {
            showValidationMessage();
            return prevValue;
        }
    }

    private void showValidationMessage() {
        Messages messages = AppBeans.get(Messages.NAME);
        DesktopComponentsHelper.getTopLevelFrame(this).showNotification(
                messages.getMessage(AppConfig.getMessagesPack(), "validationFail"),
                IFrame.NotificationType.TRAY
        );
    }

    public void setResolution(DateField.Resolution resolution) {
        this.resolution = resolution;
        if (resolution.ordinal() <= DateField.Resolution.SEC.ordinal()) {
            setShowSeconds(true);
        } else if (resolution.ordinal() <= DateField.Resolution.MIN.ordinal()) {
            setShowSeconds(false);
        } else if (resolution.ordinal() <= DateField.Resolution.HOUR.ordinal()) {
            StringBuilder builder = new StringBuilder(timeFormat);
            int minutesIndex = builder.indexOf(":mm");
            builder.delete(minutesIndex, minutesIndex + 3);
            timeFormat = builder.toString();
            setShowSeconds(false);
        }
    }

    public DateField.Resolution getResolution() {
        return resolution;
    }

    @Override
    public void setShowSeconds(boolean showSeconds) {
        this.showSeconds = showSeconds;
        if (showSeconds) {
            if (!timeFormat.contains(":ss")) {
                int minutesIndex = timeFormat.indexOf("mm");
                StringBuilder builder = new StringBuilder(timeFormat);
                builder.insert(minutesIndex + 2, ":ss");
                timeFormat = builder.toString();
            }
        } else {
            if (timeFormat.contains(":ss")) {
                int secondsIndex = timeFormat.indexOf(":ss");
                StringBuilder builder = new StringBuilder(timeFormat);
                builder.delete(secondsIndex, secondsIndex + 3);
                timeFormat = builder.toString();
            }
        }
        updateTimeFormat();
        updateWidth();
    }

    private void updateTimeFormat() {
        mask = StringUtils.replaceChars(timeFormat, "Hhmsa", "####U");
        try {
            formatter.setMask(mask);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        impl.setValue(impl.getValue());
    }

    @Override
    public Datasource getDatasource() {
        return null;
    }

    @Override
    public MetaProperty getMetaProperty() {
        return null;
    }

    @Override
    public MetaPropertyPath getMetaPropertyPath() {
        return metaPropertyPath;
    }

    @Override
    public void setDatasource(Datasource datasource, String property) {
        this.datasource = datasource;

        if (datasource == null) {
            setValue(null);
            return;
        }<commit_msg>DesktopFieldGroup#applyPermissions NPE bug #PL-4664<commit_after>/*
 * Copyright (c) 2008-2013 Haulmont. All rights reserved.
 * Use is subject to license terms, see http://www.cuba-platform.com/license for details.
 */

package com.haulmont.cuba.desktop.gui.components;

import com.haulmont.chile.core.datatypes.Datatypes;
import com.haulmont.chile.core.model.MetaClass;
import com.haulmont.chile.core.model.MetaProperty;
import com.haulmont.chile.core.model.MetaPropertyPath;
import com.haulmont.chile.core.model.utils.InstanceUtils;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.global.*;
import com.haulmont.cuba.desktop.sys.DesktopToolTipManager;
import com.haulmont.cuba.desktop.sys.vcl.Flushable;
import com.haulmont.cuba.gui.AppConfig;
import com.haulmont.cuba.gui.components.DateField;
import com.haulmont.cuba.gui.components.IFrame;
import com.haulmont.cuba.gui.components.TimeField;
import com.haulmont.cuba.gui.data.Datasource;
import com.haulmont.cuba.gui.data.impl.DsListenerAdapter;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;

import javax.swing.*;
import javax.swing.text.MaskFormatter;
import java.awt.*;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import static com.haulmont.bali.util.Preconditions.checkNotNullArgument;

/**
 * @author krivopustov
 * @version $Id$
 */
public class DesktopTimeField extends DesktopAbstractField<JFormattedTextField> implements TimeField {

    private boolean showSeconds;
    private String timeFormat;
    private String mask;
    private MaskFormatter formatter;
    private boolean updatingInstance;
    private Datasource datasource;
    private MetaProperty metaProperty;
    private MetaPropertyPath metaPropertyPath;
    private Object prevValue;
    private String caption;
    private DateField.Resolution resolution;
    private boolean editable = true;

    protected static final int DIGIT_WIDTH = 23;

    public DesktopTimeField() {
        UserSessionSource uss = AppBeans.get(UserSessionSource.NAME);

        timeFormat = Datatypes.getFormatStrings(uss.getLocale()).getTimeFormat();
        resolution = DateField.Resolution.MIN;
        formatter = new MaskFormatter();
        formatter.setPlaceholderCharacter('_');
        impl = new FlushableFormattedTextField(formatter);
        FieldListener listener = new FieldListener();
        impl.addFocusListener(listener);
        impl.addKeyListener(listener);

        setShowSeconds(timeFormat.contains("ss"));
    }

    @Override
    public boolean getShowSeconds() {
        return showSeconds;
    }

    private Object validateRawValue(String value) throws NumberFormatException, ParseException {
        if (value.equals(StringUtils.replaceChars(mask, "#U", "__")))
            return null;

        SimpleDateFormat sdf = new SimpleDateFormat(timeFormat);
        sdf.setLenient(false);
        try {
            return sdf.parse(value);
        } catch (ParseException e) {
            showValidationMessage();
            return prevValue;
        }
    }

    private void showValidationMessage() {
        Messages messages = AppBeans.get(Messages.NAME);
        DesktopComponentsHelper.getTopLevelFrame(this).showNotification(
                messages.getMessage(AppConfig.getMessagesPack(), "validationFail"),
                IFrame.NotificationType.TRAY
        );
    }

    public void setResolution(DateField.Resolution resolution) {
        this.resolution = resolution;
        if (resolution.ordinal() <= DateField.Resolution.SEC.ordinal()) {
            setShowSeconds(true);
        } else if (resolution.ordinal() <= DateField.Resolution.MIN.ordinal()) {
            setShowSeconds(false);
        } else if (resolution.ordinal() <= DateField.Resolution.HOUR.ordinal()) {
            StringBuilder builder = new StringBuilder(timeFormat);
            int minutesIndex = builder.indexOf(":mm");
            builder.delete(minutesIndex, minutesIndex + 3);
            timeFormat = builder.toString();
            setShowSeconds(false);
        }
    }

    public DateField.Resolution getResolution() {
        return resolution;
    }

    @Override
    public void setShowSeconds(boolean showSeconds) {
        this.showSeconds = showSeconds;
        if (showSeconds) {
            if (!timeFormat.contains(":ss")) {
                int minutesIndex = timeFormat.indexOf("mm");
                StringBuilder builder = new StringBuilder(timeFormat);
                builder.insert(minutesIndex + 2, ":ss");
                timeFormat = builder.toString();
            }
        } else {
            if (timeFormat.contains(":ss")) {
                int secondsIndex = timeFormat.indexOf(":ss");
                StringBuilder builder = new StringBuilder(timeFormat);
                builder.delete(secondsIndex, secondsIndex + 3);
                timeFormat = builder.toString();
            }
        }
        updateTimeFormat();
        updateWidth();
    }

    private void updateTimeFormat() {
        mask = StringUtils.replaceChars(timeFormat, "Hhmsa", "####U");
        try {
            formatter.setMask(mask);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        impl.setValue(impl.getValue());
    }

    @Override
    public Datasource getDatasource() {
        return datasource;
    }

    @Override
    public MetaProperty getMetaProperty() {
        return metaProperty;
    }

    @Override
    public MetaPropertyPath getMetaPropertyPath() {
        return metaPropertyPath;
    }

    @Override
    public void setDatasource(Datasource datasource, String property) {
        this.datasource = datasource;

        if (datasource == null) {
            setValue(null);
            return;
        }
{'fraction_non_alphanumeric': 0.10023565056387813, 'fraction_numerical': 0.002524827470122875, 'mean_word_length': 2.887144259077527, 'pattern_counts': {'":': 10, '<': 11, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4233850', 'n_tokens_mistral': 3318, 'n_tokens_neox': 3161, 'n_words': 645}