io.mapzone.controller.ui.StartPanel.java Source code

Java tutorial

Introduction

Here is the source code for io.mapzone.controller.ui.StartPanel.java

Source

/* 
 * mapzone.io
 * Copyright (C) 2016, the @authors. All rights reserved.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 3.0 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 */
package io.mapzone.controller.ui;

import static org.apache.commons.lang3.StringUtils.substringBefore;
import static org.polymap.core.ui.FormDataFactory.on;

import java.util.List;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.google.common.collect.Lists;

import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;

import org.polymap.core.runtime.UIThreadExecutor;
import org.polymap.core.runtime.event.EventHandler;
import org.polymap.core.security.SecurityContext;
import org.polymap.core.ui.FormDataFactory;
import org.polymap.core.ui.FormDataFactory.Alignment;
import org.polymap.core.ui.FormLayoutFactory;
import org.polymap.core.ui.UIUtils;

import org.polymap.rhei.batik.BatikApplication;
import org.polymap.rhei.batik.PanelIdentifier;
import org.polymap.rhei.batik.PropertyAccessEvent;
import org.polymap.rhei.batik.toolkit.ConstraintData;
import org.polymap.rhei.batik.toolkit.ConstraintLayout;
import org.polymap.rhei.batik.toolkit.IPanelSection;
import org.polymap.rhei.batik.toolkit.LayoutSupplier;

import org.polymap.cms.ContentProvider;
import org.polymap.cms.ContentProvider.ContentObject;

import io.mapzone.controller.ui.user.RegisterPanel;
import io.mapzone.controller.um.repository.LoginCookie;
import io.mapzone.controller.um.repository.User;

/**
 * Landing page or open {@link DashboardPanel} if {@link LoginCookie} is set.
 *
 * @author <a href="http://www.polymap.de">Falko Brutigam</a>
 */
public class StartPanel extends CtrlPanel {

    private static Log log = LogFactory.getLog(StartPanel.class);

    public static final PanelIdentifier ID = PanelIdentifier.parse("start");

    private Composite parent;

    @Override
    public boolean wantsToBeShown() {
        return getSite().getPath().size() == 1;
    }

    @Override
    public void createContents(@SuppressWarnings("hiding") Composite parent) {
        this.parent = parent;
        site().setSize(SIDE_PANEL_WIDTH2, 550, Integer.MAX_VALUE);
        site().title.set("mapzone");

        // login cookie -> dashboard
        Optional<LoginCookie> loginCookie = LoginCookie.access().findAndUpdate();
        if (loginCookie.isPresent()) {
            User cookieUser = loginCookie.get().user.get();
            userPrincipal.set(SecurityContext.instance().loginTrusted(cookieUser.name.get()));
            log.info("Cookie user: " + userPrincipal.get().getName());

            openDashboard();

            // frontpage, always created in case we get back from dashboard
            // but delay to avoid frontpage showing short before dashboard
            UIThreadExecutor.async(() -> {
                createFrontpageContents();
            });
        } else {
            userPrincipal.addListener(this,
                    (PropertyAccessEvent ev) -> ev.getType() == PropertyAccessEvent.TYPE.SET);
            createFrontpageContents();
        }
    }

    protected void createFrontpageContents() {
        parent.setLayout(FormLayoutFactory.defaults().spacing(10).margins(10, 0, 10, 0).create());

        ContentProvider cp = ContentProvider.instance();
        List<String> specials = Lists.newArrayList("1welcome", "99bottom");

        // banner
        Composite banner = tk().createComposite(parent, SWT.BORDER);
        banner.setBackground(UIUtils.getColor(60, 70, 80));
        FormDataFactory.on(banner).fill().noBottom(); //.height( 200 )
        banner.setLayout(FormLayoutFactory.defaults().margins(0, 0).create());

        Label welcome = new Label(banner, SWT.WRAP) {
            @Override
            public Point computeSize(int wHint, int hHint, boolean changed) {
                // suppress default text size computation in order to avoid flickering
                // caused by client side font size determination
                double area = 596 * 222;
                int height = Math.max(Math.min((int) (area / wHint), 350), 250);
                Point result = new Point(wHint, height);
                //log.info( "" + result );
                return result;
            }
        };
        tk().adapt(welcome, false, false);
        String welcomeContent = cp.findContent("frontpage/1welcome.md").content();
        welcome.setText(tk().markdownToHtml(welcomeContent, welcome));
        on(welcome).fill().left(10).right(60);

        // btn
        Matcher matcher = Pattern.compile("^button.text=(.+)$", Pattern.MULTILINE).matcher(welcomeContent);
        String btnText = matcher.find() ? matcher.group(1) : "Join...";
        Composite btnContainer = tk().createComposite(banner);
        FormDataFactory.on(btnContainer).fill().left(65).right(100);
        btnContainer.setLayout(FormLayoutFactory.defaults().create());
        Control filled = on(tk().createComposite(btnContainer)).fill().control();
        Button btn = on(tk().createButton(btnContainer, btnText, SWT.PUSH)).top(filled, 0, Alignment.CENTER)
                .left(10).height(45).width(135).control();
        btn.setToolTipText("Create an accountTest drive mapzone for free");
        btn.moveAbove(null);
        btn.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent ev) {
                getContext().openPanel(site().path(), RegisterPanel.ID);
            }
        });
        welcome.moveAbove(null);

        // article grid
        Composite grid = on(tk().createComposite(parent)).fill().top(banner).bottom(100, -80).control();
        LayoutSupplier layoutPrefs = BatikApplication.instance().getAppDesign().getPanelLayoutPreferences();
        grid.setLayout(new ConstraintLayout(layoutPrefs).setMaxColumns(3));

        for (ContentObject co : cp.listContent("frontpage")) {
            if (co.contentType().startsWith("text") && !specials.contains(co.name())) {
                createArticleSection(grid, co);
            }
        }

        // bottom links
        Composite bottom = on(tk().createComposite(parent)).fill().top(100, -40).control();
        bottom.setLayout(FormLayoutFactory.defaults().create());
        filled = on(tk().createComposite(bottom)).fill().control();
        on(tk().createFlowText(bottom, cp.findContent("frontpage/99bottom.md").content())).fill()
                .left(filled, 0, Alignment.CENTER).control().moveAbove(null);
    }

    protected void createArticleSection(Composite grid, ContentObject co) {
        String content = co.content();
        String title = co.title();
        if (content.startsWith("#")) {
            title = substringBefore(content, "\n").substring(1);
            content = content.substring(title.length() + 2);
        }

        IPanelSection section = tk().createPanelSection(grid, title, SWT.BORDER);

        int priority = 100 - Integer.parseInt(co.name().substring(0, 2));
        section.getControl().setLayoutData(new ConstraintData().prio(priority).minHeight(300).minWidth(350)); //.maxWidth( 450 ) );
        //ColumnDataFactory.defaults().heightHint( 300 ).widthHint( 350 ).create() );

        section.getBody().setLayout(FormLayoutFactory.defaults().create());

        // this generates an iFrame with proper size; this allows to load
        // scripts/CSS in content *and* is better than a Label which always has
        // its own idea of its size depending on fonts in content
        Browser b = new Browser(section.getBody(), SWT.NONE);
        on(b).fill().width(380);

        // XXX moved <head> elements in a <p> which generates a margin on top
        String html = tk().markdownToHtml(content, b);
        b.setText(html);
    }

    /**
     * Page layout: 800px width    
     */
    protected void createPageLayout() {
        ((ConstraintLayout) parent.getLayout()).setMargins(new LayoutSupplier() {
            LayoutSupplier layoutPrefs = site().layoutPreferences();
            LayoutSupplier appLayoutPrefs = BatikApplication.instance().getAppDesign().getAppLayoutSettings();

            @Override
            public int getSpacing() {
                return 0; //layoutPrefs.getSpacing() * 2;
            }

            protected int margins() {
                Rectangle bounds = parent.getParent().getBounds();
                int availWidth = bounds.width - (appLayoutPrefs.getMarginLeft() + appLayoutPrefs.getMarginRight());
                return Math.max((availWidth - 800) / 2, layoutPrefs.getMarginLeft());
            }

            @Override
            public int getMarginTop() {
                return layoutPrefs.getMarginTop();
            }

            @Override
            public int getMarginRight() {
                return margins();
            }

            @Override
            public int getMarginLeft() {
                return margins();
            }

            @Override
            public int getMarginBottom() {
                return layoutPrefs.getMarginBottom() /*+ 10*/;
            }
        });
    }

    protected void openDashboard() {
        // make StartPanel/frontpage to big to be shown beside the dashboard
        site().preferredWidth.set(Integer.MAX_VALUE);
        site().minWidth.set(Integer.MAX_VALUE);

        UIThreadExecutor.async(() -> getContext().openPanel(getSite().getPath(), DashboardPanel.ID));
    }

    /** 
     * Triggered by {@link StartPanel} and {@link RegisterPanel}.
     */
    @EventHandler(display = true)
    protected void userLogedIn(PropertyAccessEvent ev) {
        openDashboard();
    }

}