/*
* Copyright 2003-2010 Tufts University Licensed under the
* Educational Community License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.osedu.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS"
* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package tufts.vue;
import tufts.Util;
import tufts.vue.NodeTool.NodeModeTool;
import java.util.Collection;
import java.awt.Color;
import java.awt.Font;
/**
* A subclass of LWSlide that handles special behaviour for MasterSlides,
* such as providing editable slide style objects when the MasterSlide
* is the the current focal.
*
* @author Scott Fraize
* @version $Revision: 1.18 $ / $Date: 2010-02-03 19:17:41 $ / $Author: mike $
*/
public final class MasterSlide extends LWSlide
{
protected static final org.apache.log4j.Logger Log = org.apache.log4j.Logger.getLogger(MasterSlide.class);
final static String TitleLabel = "Slide Title Style";
final static String TextLabel = "Slide Text Style";
final static String URLLabel = "Link";
private LWComponent headerStyle;
private LWComponent textStyle;
private LWComponent linkStyle;
/** for castor persistance */
public MasterSlide() {
initMaster();
}
// /** @return false: prevents every drawing selection on map */
// @Override
// public boolean isMapVirtual() {
// return true;
// }
/** @return null -- don't create a style type for master slides */
@Override
public Object getTypeToken() {
return null;
}
@Override
public final void setParent(LWContainer parent) {
if (parent instanceof LWPathway) {
super.setParent(parent);
setPathwayEntry(((LWPathway)parent).asEntry());
} else
Util.printStackTrace(this + " master slide can't set parent to non pathway: " + parent);
}
@Override
public double getScale() { return 1.0; }
@Override
public void takeScale(double s) {}
@Override
public boolean isMoveable() { return false; }
// /** @return true */
// @Override
// public boolean isPathwayOwned() {
// return true;
// }
void completeXMLRestore() {
if (true) {
// just in case -- some save file versions could get these messed up
setX(0);
setY(0);
super.takeScale(1.0);
takeSize(LWSlide.SlideWidth, LWSlide.SlideHeight);
}
if (headerStyle == null) {
// all the style objects will be null for old-style (pre 2007-09-07) master slides
for (LWComponent c : getChildren()) {
if (!c.hasLabel())
continue;
final String label = c.getLabel();
if ("Sample Text".equals(c.getLabel()) || label.startsWith("Slide Text")) {
textStyle = c;
if (DEBUG.IO||DEBUG.PRESENT) out("FOUND OLD TEXT STYLE " + c);
} else if (label.startsWith("Slide Title")) {
//} else if ("Header Text".equals(label) || label.startsWith("Slide Title")) {
if (DEBUG.IO||DEBUG.PRESENT) out("FOUND OLD TITLE STYLE " + c);
headerStyle = c;
} else if (label.startsWith("http:")) {
if (DEBUG.IO||DEBUG.PRESENT) out("FOUND OLD URL STYLE " + c);
linkStyle = c;
} else if (c.isStyle()) {
Util.printStackTrace(this + "; Missed old-master-slide style object: " + c);
}
}
// old-style master slide persisted this as children: no longer -- remove them
if (headerStyle != null) mChildren.remove(headerStyle);
if (textStyle != null) mChildren.remove(textStyle);
if (linkStyle != null) mChildren.remove(linkStyle);
ensureStylesCreated();
// in case we somehow missed finding the old-type style objects
}
initStyles();
// todo for recent back compat: if styles not on master slide, add them
}
private void initMaster() {
enableProperty(LWKey.Label);
setFlag(Flag.LOCKED);
setFlag(Flag.FIXED_LOCATION);
}
/** create a new master slide for a newly create pathway */
MasterSlide(final LWPathway owner)
{
initMaster();
setStrokeWidth(0);
setFillColor(Color.black);
setSize(SlideWidth, SlideHeight);
setPathwayEntry(owner.asEntry());
//if (owner != null) setFillColor(owner.getStrokeColor()); // debug: use the pathway stroke as slide color
// Create the default items for the master slide:
if (owner != null) {
setParent(owner); // must do before initStyles
ensureID(this);
}
ensureStylesCreated();
initStyles();
}
private void ensureStylesCreated() {
if (headerStyle == null) {
headerStyle = NodeModeTool.buildTextNode(TitleLabel);
headerStyle.setFont(new Font("Gill Sans", Font.PLAIN, 36));
headerStyle.setTextColor(Color.white);
}
if (textStyle == null) {
textStyle = NodeModeTool.buildTextNode(TextLabel);
textStyle.setFont(new Font("Gill Sans", Font.PLAIN, 22));
textStyle.setTextColor(Color.white);
}
if (linkStyle == null) {
linkStyle = NodeModeTool.buildTextNode(URLLabel);
linkStyle.setFont(new Font("Gill Sans", Font.PLAIN, 18));
linkStyle.setTextColor(new Color(179, 191, 227));
}
}
private void initStyles() {
//headerStyle.takeLocation(40,30);
headerStyle.takeLocation(0,0);
headerStyle.setLabel("Header");
initStyle(headerStyle);
//textStyle.takeLocation(45,110);
textStyle.takeLocation(0,0);
textStyle.setLabel("Slide Text");
initStyle(textStyle);
//linkStyle.takeLocation(45,180);
linkStyle.takeLocation(0,0);
linkStyle.setLabel("Links");
initStyle(linkStyle);
//mFillColor.setAllowAlpha(false);
final LWSelection s = new LWSelection(headerStyle);
s.setTo(headerStyle);
Actions.AlignCentersRow.act(s);
Actions.AlignCentersColumn.act(s);
s.setTo(textStyle);
Actions.AlignCentersRow.act(s);
Actions.AlignCentersColumn.act(s);
s.setTo(linkStyle);
Actions.AlignCentersRow.act(s);
Actions.AlignCentersColumn.act(s);
headerStyle.translate(0, -100);
linkStyle.translate(0, +100);
}
private void initStyle(LWComponent style) {
style.setPersistIsStyle(Boolean.TRUE);
style.setFlag(Flag.FIXED_LOCATION);
style.disableProperty(LWKey.Label);
style.setMoveable(false);
style.setParent(this); // styles are "viritual children" -- not in parent child list
this.ensureID(style);
}
// private void createDefaultComponents() {
// LWComponent header = NodeModeTool.buildTextNode("Header Text");
// header.setFont(headerStyle.getFont().deriveFont(16f));
// header.setTextColor(VueResources.makeColor("#b3bfe3"));
// LWComponent footer = header.duplicate();
// footer.setLabel("Footer Text");
// // Now that the footer is parented, move it to lower right in it's parent
// LWSelection s = new LWSelection(header);
// s.setTo(header);
// Actions.AlignRightEdges.act(s);
// Actions.AlignTopEdges.act(s);
// s.setTo(footer);
// Actions.AlignRightEdges.act(s);
// Actions.AlignBottomEdges.act(s);
// }
public LWComponent getTitleStyle() {
return headerStyle;
}
public void setTitleStyle(LWComponent style) {
if (DEBUG.IO||DEBUG.PRESENT) Log.debug("setHeaderStyle " + style);
headerStyle = style;
}
public LWComponent getTextStyle() {
return textStyle;
}
public void setTextStyle(LWComponent style) {
if (DEBUG.IO||DEBUG.PRESENT) Log.debug("setTextStyle " + style);
textStyle = style;
}
/** @return the style for hyper-links (e.g., URL's) */
public LWComponent getLinkStyle() {
return linkStyle;
}
public void setLinkStyle(LWComponent style) {
if (DEBUG.IO||DEBUG.PRESENT) Log.debug("setLinkStyle " + style);
linkStyle = style;
}
/** @return false: master slide can never sync */
@Override
public boolean canSync() {
return false;
}
// /** @return false: master slide applies no styles of it's own */
// @Override
// boolean applyStyle(LWComponent c) {
// return false;
// }
// @Override
// public void synchronizeResources(Sync type) {
// Util.printStackTrace("Cannot sync a MasterSlide: " + this + " type(" + type + ")");
// }
@Override
public Color getRenderFillColor(DrawContext dc) {
return getFillColor();
}
//private static final Font EditLabelFont = new Font("SansSerif", Font.PLAIN, 72);
private static final Font EditLabelFont = new Font("Gill Sans", Font.PLAIN, 72);
private static final Color EditLabelColorDarkBG = new Color(255,255,255,64);
private static final Color EditLabelColorLightBG = new Color(0,0,0,64);
// skip fancy LWComponent stuff, and draw background
@Override
public void draw(DrawContext dc) {
// TODO: this is now over-drawn when in presentation mode
// and even for node icons I think... (because the master
// slide is never the focal, and because we can't just check
// the focal for being a slide or portal, as it could be
// a map-view node)
// Actually, totally recheck this. Good enough for now tho.
//Util.printStackTrace("DRAWING in " + dc);
final Color bgFill = dc.getBackgroundFill();
if (!getFillColor().equals(bgFill)) {
dc.g.setColor(getFillColor());
dc.g.fill(getZeroShape());
}
if (dc.focal == this) {
dc.g.setFont(EditLabelFont);
if (mFillColor.brightness() < 0.5)
dc.g.setColor(EditLabelColorDarkBG);
else
dc.g.setColor(EditLabelColorLightBG);
dc.g.drawString("Master Slide", 72/4, 72);
if (true||DEBUG.Enabled) {
//dc.g.setColor(Color.red);
dc.g.drawString(getEntry().pathway.getLabel(), 72/4, getHeight() - 72/4);
}
}
drawImpl(dc);
}
// // we could not have a special master slide object if we could handle
// // this draw-skipping in some other way (and arbitrary nodes can be style master's)
// // Tho having a special master-slide object isn't really that big a deal.
// @Override
// protected void drawChild(LWComponent child, DrawContext dc) {
// if (dc.focal != this && !child.isMoveable())
// return;
// else
// super.drawChild(child, dc);
// }
@Override
public String getLabel() {
if (mXMLRestoreUnderway)
return null;
else
{
if (getEntry() != null && getEntry().pathway != null)
return getEntry().pathway.getLabel();
else
return null;
}
}
@Override public void setLabel(String label) {
if (mXMLRestoreUnderway)
; // ignore
else
getEntry().pathway.setLabel(label);
}
@Override public boolean hasLabel() { return true; }
/** @return true -- always has picks, even if no proper children (the slide style objects) */
@Override public boolean hasPicks() {
return true;
}
// override LWSlide impl that tries to draw master slide -- only draw children -- no fill
@Override protected void drawImpl(DrawContext dc) {
drawChildren(dc);
if (dc.focal == this) {
headerStyle.drawLocal(dc.push()); dc.pop();
textStyle.drawLocal(dc.push()); dc.pop();
linkStyle.drawLocal(dc.push()); dc.pop();
}
}
@Override public java.util.List<LWComponent> getPickList(PickContext pc, java.util.List<LWComponent> stored)
{
stored.clear();
stored.addAll(getChildren());
stored.add(headerStyle);
stored.add(textStyle);
stored.add(linkStyle);
return stored;
}
@Override public Collection<LWComponent> getAllDescendents(final ChildKind kind, final Collection bag, Order order)
{
if (kind == ChildKind.ANY) {
bag.add(headerStyle);
bag.add(textStyle);
bag.add(linkStyle);
}
return super.getAllDescendents(kind, bag, order);
}
/** @return true -- is never considered "empty" */
@Override public boolean hasContent() {
return true;
}
/** @return true */
@Override public boolean hasDraws() {
return true;
}
/** @return true */
@Override public boolean isVisible() {
return true;
}
// For backward compatability with old save files, we
// re-route notes to the notes stored for the pathway
// itself. The notes for the MasterSlide object itself
// will remain unused.
@Override public String getNotes() {
return getEntry().pathway.getNotes();
}
@Override public boolean hasNotes() {
return getEntry().pathway.hasNotes();
}
// public String getLabel() {
// return "Master Slide: " + (getParent() == null ?" <unowned>" : getParent().getDisplayLabel());
// }
public String getComponentTypeLabel() { return "Pathway/Master"; }
//public String getComponentTypeLabel() { return "Slide<Master>"; }
}