com.codename1.ui.util.GlassTutorial Maven / Gradle / Ivy
/*
* Copyright (c) 2012, Codename One and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Codename One designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Codename One through http://www.codenameone.com/ if you
* need additional information or have any questions.
*/
package com.codename1.ui.util;
import com.codename1.ui.Component;
import com.codename1.ui.Dialog;
import com.codename1.ui.Display;
import com.codename1.ui.Form;
import com.codename1.ui.Graphics;
import com.codename1.ui.Label;
import com.codename1.ui.Painter;
import com.codename1.ui.geom.Dimension;
import com.codename1.ui.geom.Rectangle;
import com.codename1.ui.layouts.BorderLayout;
import com.codename1.ui.plaf.Style;
import com.codename1.ui.plaf.UIManager;
import java.util.Vector;
/**
* A Glass Tutorial appears on top of the UI especially on a touch device
* but could be on any device and points to/circles components within the UI
* coupled with explanation of what they do and a tint of the screen.
* It is implemented as a GlassPane on top of a Form which is automatically
* removed when a user touches the screen or presses a button.
* To position elements within the glass tutorial the elements must be
* associated with a component instance of the underlying UI and positioned
* relatively to said component.
* The GlassTutorial uses the "GlassTutorial" UIID to paint itself it then paints
* the hint components in their proper places.
*
* @author Shai Almog
* @deprecated interaction dialog is a superior way for displaying these types of tutorials
*/
public class GlassTutorial implements Painter {
private static final String DEST = "$$GLSDESTHINT$$";
private static final String POS = "$$GLSDESTPOS$$";
private Vector vec = new Vector();
private Component internal;
/**
* Places a hint within the glass in a position relative to the destinationComponent, the position
* is indicated with border layout attributes. Notice you can place multiple components on a single
* element and they will be rendered in order e.g. a component with a border can be used to "circle"
* the destination by placing it in the CENTER position and another arrow with text can be places in
* the south position below.
*
* @param hintComponent The component that would be renderered in the given position
* @param destinationComponent the "hinted" component over which the hint will show
* @param position the position relative to the destinationComponent in BorderLayout values e.g. to place the hint
* above the component just place it in BorderLayout.NORTH. The center will stretch the component but the
* other sides will give the component its exact preferred size.
*/
public void addHint(Component hintComponent, Component destinationComponent, String position) {
hintComponent.putClientProperty(POS, position);
hintComponent.putClientProperty(DEST, destinationComponent);
vec.addElement(hintComponent);
}
/**
* Install the glass tutorial on a form and seamlessly dismiss it when no longer necessary
* @param f the form
*/
public void showOn(Form f) {
Painter oldPane = f.getGlassPane();
f.setGlassPane(this);
Dialog dummy = new Dialog() {
public void keyReleased(int i) {
dispose();
}
};
int oldTint = f.getTintColor();
f.setTintColor(0);
dummy.getDialogStyle().setBgTransparency(0);
dummy.setDisposeWhenPointerOutOfBounds(true);
dummy.show(0, Display.getInstance().getDisplayHeight() - 2, 0, Display.getInstance().getDisplayWidth() - 2, true, true);
f.setTintColor(oldTint);
f.setGlassPane(oldPane);
}
/**
* {@inheritDoc}
*/
public void paint(Graphics g, Rectangle rect) {
if(internal == null) {
internal = new Label(" ");
internal.setUIID("GlassTutorial");
}
internal.setSize(rect.getSize());
internal.paintComponent(g);
int componentCount = vec.size();
for(int iter = 0 ; iter < componentCount ; iter++) {
Component current = (Component)vec.elementAt(iter);
String pos = (String)current.getClientProperty(POS);
Component dest = (Component)current.getClientProperty(DEST);
int xpos = dest.getAbsoluteX();
int ypos = dest.getAbsoluteY();
int w = dest.getWidth();
int h = dest.getHeight();
if(pos.equals(BorderLayout.CENTER)) {
current.setX(xpos);
current.setY(ypos);
current.setWidth(w);
current.setHeight(h);
current.paintComponent(g);
continue;
}
Dimension d = current.getPreferredSize();
current.setWidth(d.getWidth());
current.setHeight(d.getHeight());
if(pos.equals(BorderLayout.SOUTH)) {
current.setX(xpos + w / 2 - d.getWidth() / 2);
current.setY(ypos + h);
current.paintComponent(g);
continue;
}
if(pos.equals(BorderLayout.NORTH)) {
current.setX(xpos + w / 2 - d.getWidth() / 2);
current.setY(ypos - d.getHeight());
current.paintComponent(g);
continue;
}
if(pos.equals(BorderLayout.EAST)) {
current.setX(xpos + w);
current.setY(ypos + h / 2 - d.getHeight() / 2);
current.paintComponent(g);
continue;
}
if(pos.equals(BorderLayout.WEST)) {
current.setX(xpos - d.getWidth());
current.setY(ypos + h / 2 - d.getHeight() / 2);
current.paintComponent(g);
continue;
}
}
}
}