001    package org.kuali.student.common.ui.client.mvc.breadcrumb;
002    
003    import java.util.ArrayList;
004    import java.util.List;
005    
006    import org.kuali.student.common.ui.client.mvc.Controller;
007    import org.kuali.student.common.ui.client.mvc.history.HistoryManager;
008    import org.kuali.student.common.ui.client.widgets.field.layout.element.SpanPanel;
009    
010    import com.google.gwt.user.client.ui.ComplexPanel;
011    import com.google.gwt.user.client.ui.Composite;
012    import com.google.gwt.user.client.ui.Hyperlink;
013    import com.google.gwt.user.client.ui.InlineLabel;
014    import com.google.gwt.user.client.ui.Panel;
015    import com.google.gwt.user.client.ui.Widget;
016    
017    /**
018     * Manages breadcrumbs for the application
019     * 
020     * @author Kuali Student Team
021     *
022     */
023    public class BreadcrumbManager extends Composite{
024            
025            public static List<Hyperlink> links = new ArrayList<Hyperlink>();
026            
027            private static List<String> names = new ArrayList<String>();
028            
029            private static Controller root;
030            private static ComplexPanel panel = new SpanPanel();
031            private static boolean panelEmpty = true;
032            
033            private static Panel parentPanel;
034            
035            private static class BreadcrumbData{
036                    private String name;
037                    private String path;
038                    public BreadcrumbData(String name, String path) {
039                            super();
040                            this.name = name;
041                            this.path = path;
042                    }
043            }
044            
045            /**
046             * Binds the controller as the top level controller to call collectBreadcrumbNames on.
047             * 
048             * @param controller
049             */
050            public static void bind(Controller controller){
051                    root = controller;
052            }
053            
054            /**
055             * Updates the breadcrumb panel with the current breadcrumb by walking the controller hierarchy by calling
056             * collectBreadcrumbNames on the root controller bound to the BreadcrumbManager.
057             * 
058             * @param historyStack
059             */
060            public static void updateLinks(String historyStack){
061                if (root == null){
062                    return;
063                }
064                
065                    links.clear();
066                    panel.clear();
067                    panelEmpty = true;
068                    names.clear();
069                    root.collectBreadcrumbNames(names);
070                    
071                    String[] arr = HistoryManager.splitHistoryStack(historyStack);
072                    List<BreadcrumbData> breadcrumbs = new ArrayList<BreadcrumbData>();
073    
074                    if(arr.length == names.size()){
075                            String path = "";
076                            //account for applicationController - skip first item from both
077                            for(int i = 1; i < names.size(); i++){
078                                    path = path + "/" + arr[i];
079                                    String name = names.get(i);
080                                    //Views with empty names do not appear on the breadcrumbs
081                                    if(name != null && !name.isEmpty()){
082                                            breadcrumbs.add(new BreadcrumbData(name, path));
083                                    }
084                            }
085                    }
086                    //Special link, a controller is adding a breadcrumb outside the scope of the current controller
087                    //in format name@path
088                    else if(names.size() > arr.length){
089                            String path = "";
090                            int j = 1;
091                            //account for applicationController - skip first item from both
092                            for(int i = 1; i < names.size(); i++){
093                                    String name = names.get(i);
094                                    if(name.contains("@")){
095                                            String[] split = name.split("@");
096                                            name = split[0];
097                                            if(name != null && !name.isEmpty()){
098                                                    //In the special case the path is the second part of the split
099                                                    breadcrumbs.add(new BreadcrumbData(name, split[1]));
100                                            }
101                                    }
102                                    else{
103                                            if(j == arr.length){
104                                                    break;
105                                            }
106                                            path = path + "/" + arr[j];
107                                            j++;
108                                            if(name != null && !name.isEmpty()){
109                                                    breadcrumbs.add(new BreadcrumbData(name, path));
110                                            }
111                                    }
112                            }
113                    }
114                    
115                    if(parentPanel != null){
116                            if(breadcrumbs.size() == 1){
117                                    panel.getParent().setVisible(false);
118                            }
119                            else{
120                                    panel.getParent().setVisible(true);
121    
122                            }
123                    }
124                    
125                    for(int i = 0; i < breadcrumbs.size(); i++){
126                            if(i < breadcrumbs.size() - 1){
127                                    createLink(breadcrumbs.get(i).name, breadcrumbs.get(i).path);
128                            }
129                            else{
130                                    createLabel(breadcrumbs.get(i).name);
131                                    //WindowTitleUtils.setSubtitle(breadcrumbs.get(i).name);
132                            }
133                    }
134            }
135            
136            private static void createLabel(String name){
137                    addToPanel(new InlineLabel(name));
138            }
139            
140            private static void createLink(String name, final String viewPath){
141                    Hyperlink link = new Hyperlink(name, viewPath);
142                    links.add(link);
143                    addToPanel(link);
144            }
145            
146            private static void addToPanel(Widget w){
147                    if(panelEmpty){
148                            panel.add(w);
149                            panelEmpty = false;
150                    }
151                    else{
152                            panel.add(new InlineLabel(" \u00BB "));
153                            panel.add(w);
154                    }
155            }
156            
157            /** 
158             * @return the breadcrumb panel which contains the breadcrumb links dynamically updated by the 
159             * BreadcrumbManager
160             */
161            public static ComplexPanel getBreadcrumbPanel(){
162                    return panel;
163            }
164            
165            public static void setParentPanel(Panel panel){
166                    parentPanel = panel;
167                    parentPanel.setVisible(false);
168            }
169    
170    }