001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.wicket.extensions.breadcrumb.panel; 018 019import org.apache.wicket.Component; 020import org.apache.wicket.extensions.breadcrumb.BreadCrumbLink; 021import org.apache.wicket.extensions.breadcrumb.IBreadCrumbModel; 022import org.apache.wicket.extensions.breadcrumb.IBreadCrumbParticipant; 023import org.apache.wicket.markup.html.panel.Panel; 024import org.apache.wicket.model.IModel; 025 026 027/** 028 * A panel that participates with a {@link IBreadCrumbModel bread crumb model}. The idea is that you 029 * would have a dialog-like component that is much like a wizard, but more decoupled. A typical 030 * setup is that you have a panel, where the content is dynamic but hierarchical in nature, and that 031 * there are links on the panel that <i>take you deeper into the hierarchy<i> 032 * 033 * <p> 034 * An example of using {@link BreadCrumbPanel bread crumb panels} and {@link BreadCrumbLink bread 035 * crumb links}: 036 * 037 * <pre> 038 * add(new BreadCrumbLink("myLink", breadCrumbModel) 039 * { 040 * protected IBreadCrumbParticipant getParticipant(String componentId) 041 * { 042 * return new MyPanel(componentId, breadCrumbModel); 043 * } 044 * }); 045 * </pre> 046 * 047 * where <tt>MyPanel</tt> is a {@link BreadCrumbPanel bread crumb panel} and the link is added to 048 * another {@link BreadCrumbPanel bread crumb panel} instance (this). When clicked, MyPanel will 049 * replace the panel that the link is placed on, and it will set (and add) <tt>MyPanel</tt> as the 050 * active bread crumb in the {@link IBreadCrumbModel bread crumb component model}. 051 * </p> 052 * 053 * @author Eelco Hillenius 054 */ 055public abstract class BreadCrumbPanel extends Panel implements IBreadCrumbParticipant 056{ 057 private static final long serialVersionUID = 1L; 058 059 /** The bread crumb model. */ 060 private IBreadCrumbModel breadCrumbModel; 061 062 /** 063 * Implementation of the participant. 064 */ 065 private final IBreadCrumbParticipant decorated = new BreadCrumbParticipantDelegate(this) 066 { 067 private static final long serialVersionUID = 1L; 068 069 @Override 070 public IModel<String> getTitle() 071 { 072 return BreadCrumbPanel.this.getTitle(); 073 } 074 }; 075 076 /** 077 * Construct. 078 * 079 * @param id 080 * Component id 081 * @param breadCrumbModel 082 * The bread crumb model 083 */ 084 public BreadCrumbPanel(final String id, final IBreadCrumbModel breadCrumbModel) 085 { 086 super(id); 087 this.breadCrumbModel = breadCrumbModel; 088 } 089 090 /** 091 * Construct. 092 * 093 * @param id 094 * Component id 095 * @param breadCrumbModel 096 * The bread crumb model 097 * @param model 098 * The model 099 */ 100 public BreadCrumbPanel(final String id, final IBreadCrumbModel breadCrumbModel, 101 final IModel<?> model) 102 { 103 super(id, model); 104 this.breadCrumbModel = breadCrumbModel; 105 } 106 107 /** 108 * Activates the {@link BreadCrumbPanel bread crumb panel} that is the result of calling 109 * {@link IBreadCrumbPanelFactory#create(String, IBreadCrumbModel) the create method} of the 110 * bread crumb panel factory. 111 * 112 * @param breadCrumbPanelFactory 113 */ 114 public void activate(final IBreadCrumbPanelFactory breadCrumbPanelFactory) 115 { 116 activate(breadCrumbPanelFactory.create(getId(), breadCrumbModel)); 117 } 118 119 /** 120 * Activates the provided participant, which typically has the effect of replacing this current 121 * panel with the one provided - as the participant typically would be a {@link BreadCrumbPanel 122 * bread crumb panel} - and updating the bread crumb model of this panel, pushing the bread 123 * crumb for the given participant on top. 124 * 125 * @param participant 126 * The participant to set as the active one 127 */ 128 public void activate(final IBreadCrumbParticipant participant) 129 { 130 // get the currently active participant 131 final IBreadCrumbParticipant active = breadCrumbModel.getActive(); 132 if (active == null) 133 { 134 throw new IllegalStateException("The model has no active bread crumb. Before using " + 135 this + ", you have to have at least one bread crumb in the model"); 136 } 137 138 // add back button support 139 addStateChange(); 140 141 // set the bread crumb panel as the active one 142 breadCrumbModel.setActive(participant); 143 } 144 145 /** 146 * Gets the bread crumb panel. 147 * 148 * @return The bread crumb panel 149 */ 150 public final IBreadCrumbModel getBreadCrumbModel() 151 { 152 return breadCrumbModel; 153 } 154 155 /** 156 * The participating component == this. 157 * 158 * @see org.apache.wicket.extensions.breadcrumb.IBreadCrumbParticipant#getComponent() 159 */ 160 @Override 161 public Component getComponent() 162 { 163 return decorated.getComponent(); 164 } 165 166 /** 167 * @see org.apache.wicket.extensions.breadcrumb.IBreadCrumbParticipant#onActivate(org.apache.wicket.extensions.breadcrumb.IBreadCrumbParticipant) 168 */ 169 @Override 170 public void onActivate(final IBreadCrumbParticipant previous) 171 { 172 decorated.onActivate(previous); 173 } 174 175 /** 176 * Sets the bread crumb panel. 177 * 178 * @param breadCrumbModel 179 * The bread crumb panel 180 */ 181 public final void setBreadCrumbModel(final IBreadCrumbModel breadCrumbModel) 182 { 183 this.breadCrumbModel = breadCrumbModel; 184 } 185}