package org.jtheque.movies.views.impl; /* * Copyright JTheque (Baptiste Wicht) * * Licensed under the Apache 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.apache.org/licenses/LICENSE-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. */ import org.jtheque.images.ImageService; import org.jtheque.movies.MoviesResources; import org.jtheque.movies.persistence.od.able.Movie; import org.jtheque.movies.services.able.ICategoriesService; import org.jtheque.movies.services.able.IMoviesService; import org.jtheque.movies.views.able.IEditMovieView; import org.jtheque.movies.views.able.IMovieView; import org.jtheque.movies.views.able.models.IMoviesModel; import org.jtheque.movies.views.impl.fb.IMovieFormBean; import org.jtheque.movies.views.impl.models.CategoryElement; import org.jtheque.movies.views.impl.models.FilthyCellRenderer; import org.jtheque.movies.views.impl.models.MoviesModel; import org.jtheque.movies.views.impl.panel.MoviePanel; import org.jtheque.movies.views.impl.sort.MoviesSorter; import org.jtheque.persistence.Entity; import org.jtheque.primary.able.controller.IPrincipalController; import org.jtheque.primary.utils.views.listeners.CurrentObjectListener; import org.jtheque.primary.utils.views.listeners.DisplayListListener; import org.jtheque.primary.utils.views.listeners.ObjectChangedEvent; import org.jtheque.primary.utils.views.tree.JThequeTreeModel; import org.jtheque.primary.utils.views.tree.TreeElement; import org.jtheque.ui.components.Borders; import org.jtheque.ui.components.CardPanel; import org.jtheque.ui.components.filthy.Filthy; import org.jtheque.ui.utils.actions.ActionFactory; import org.jtheque.ui.utils.builded.OSGIFilthyBuildedPanel; import org.jtheque.ui.utils.builders.I18nPanelBuilder; import org.jtheque.ui.utils.builders.PanelBuilder; import org.jtheque.utils.ui.GridBagUtils; import org.jdesktop.swingx.JXTree; import javax.annotation.Resource; import javax.swing.JLabel; import javax.swing.tree.TreePath; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Font; import java.awt.Insets; import java.util.Collection; import static org.jtheque.ui.components.filthy.FilthyConstants.TITLE_FONT; /** * Panel to display movies. * * @author Baptiste Wicht */ public final class MovieView extends OSGIFilthyBuildedPanel implements CurrentObjectListener, IMovieView, DisplayListListener { private static final double LIST_COLUMN = 0.3; private final JThequeTreeModel treeModel = new JThequeTreeModel(new CategoryElement("Movies")); @Resource private MoviePanel viewMoviePanel; @Resource private MoviePanel editMoviePanel; @Resource private IMoviesService moviesService; @Resource private ICategoriesService categoriesService; private CardPanel<MoviePanel> layeredPanel; private JXTree treeMovies; private MoviesSorter moviesSorter; //Don't use @ResourceImpl cause of circular references private IPrincipalController<Movie, IMovieView> movieController; @Override protected void buildView(I18nPanelBuilder builder) { setModel(new MoviesModel(moviesService)); moviesSorter = new MoviesSorter(categoriesService, moviesService); buildPanelList(builder); buildPanelMovie(builder); treeMovies.addTreeSelectionListener(getMovieController()); selectFirst(); getModel().addCurrentObjectListener(this); getModel().addDisplayListListener(this); } /** * Build the internal panel list. * * @param parent The parent builder. */ private void buildPanelList(I18nPanelBuilder parent) { parent.setDefaultInsets(new Insets(2, 2, 2, 5)); I18nPanelBuilder builder = parent.addPanel(new BorderLayout(2, 2), parent.gbcSet(0, 0, GridBagUtils.BOTH, GridBagUtils.FIRST_LINE_START, LIST_COLUMN, 1.0)); parent.setDefaultInsets(new Insets(2, 2, 2, 2)); builder.getPanel().setBorder(Borders.createEmptyBorder(10, 10, 10, 20)); builder.getPanel().setMinimumSize(new Dimension(165, 400)); addTitle(builder); addTree(builder); addActions(builder); } /** * Add the title of the tree to the builder. * * @param builder The panel builder. */ private void addTitle(I18nPanelBuilder builder) { I18nPanelBuilder titleBuilder = builder.addPanel(BorderLayout.NORTH); JLabel label = titleBuilder.addI18nLabel("movie.panel.list.title", titleBuilder.gbcSet(0, 0, GridBagUtils.HORIZONTAL, GridBagUtils.BASELINE_LEADING, 1.0, 0.0)); ImageService imageService = getService(ImageService.class); titleBuilder.addButton( ActionFactory.createAction("refresh", imageService.getIcon(MoviesResources.REFRESH_ICON), getMovieController()), titleBuilder.gbcSet(1, 0)); titleBuilder.addButton( ActionFactory.createAction("expand", imageService.getIcon(MoviesResources.EXPAND_ICON), getMovieController()), titleBuilder.gbcSet(2, 0)); titleBuilder.addButton( ActionFactory.createAction("collapse", imageService.getIcon(MoviesResources.COLLAPSE_ICON), getMovieController()), titleBuilder.gbcSet(3, 0)); label.setFont(TITLE_FONT.deriveFont(25.0f)); } /** * Add the tree to the builder. * * @param builder The panel builder. */ private void addTree(PanelBuilder builder) { moviesSorter.sort(treeModel); treeMovies = (JXTree) builder.addScrolledTree(treeModel, new FilthyCellRenderer(getService(ImageService.class)), BorderLayout.CENTER); } /** * Add the add actions to the view. * * @param builder The panel builder. */ private void addActions(I18nPanelBuilder builder) { I18nPanelBuilder panelButtons = builder.addPanel(BorderLayout.SOUTH); panelButtons.addI18nLabel("movie.panel.list.new", Font.BOLD, builder.gbcSet(0, 0, GridBagUtils.NONE, GridBagUtils.BASELINE_LEADING, LIST_COLUMN, 0.0)); panelButtons.addButton(ActionFactory.createAction("movie.actions.add", getMovieController()), builder.gbcSet(0, 1, GridBagUtils.NONE, GridBagUtils.BASELINE_LEADING, LIST_COLUMN, 0.0)); panelButtons.addButton(ActionFactory.createAction("movie.auto.actions.add", getMovieController()), builder.gbcSet(0, 2, GridBagUtils.NONE, GridBagUtils.BASELINE_LEADING, 1, 1, LIST_COLUMN, 0.0, 10, 0)); } /** * Build the internal panel film. * * @param parent The parent builder. */ private void buildPanelMovie(PanelBuilder parent) { layeredPanel = Filthy.newCardPanel(); layeredPanel.addLayer(viewMoviePanel, viewMoviePanel.getKey()); layeredPanel.addLayer(editMoviePanel, editMoviePanel.getKey()); setDisplayedView(VIEW_VIEW); parent.add(layeredPanel, parent.gbcSet(1, 0, GridBagUtils.BOTH, GridBagUtils.FIRST_LINE_START, 1 - LIST_COLUMN, 1.0)); } @Override public void displayListChanged() { moviesSorter.sort(treeModel); } @Override public void validate(Collection<org.jtheque.errors.Error> errors) { layeredPanel.getCurrentLayer().validate(errors); } @Override public void objectChanged(ObjectChangedEvent event) { layeredPanel.getCurrentLayer().setMovie((Movie) event.getObject()); } @Override public IMovieFormBean fillMovieFormBean() { return layeredPanel.getCurrentLayer().fillMovieFormBean(); } @Override public void setDisplayedView(String view) { layeredPanel.displayLayer(view); } @Override public MoviePanel getCurrentView() { return layeredPanel.getCurrentLayer(); } @Override public void select(Movie movie) { select(movie, treeModel.getRoot(), new TreePath(treeModel.getRoot())); } /** * Select the specified movie in the tree. * * @param movie The movie to select. * @param root The current element to search in. * @param path The current search path. * * @return true if the movie has been selected else false. */ private boolean select(Movie movie, TreeElement root, TreePath path) { for (int i = 0; i < treeModel.getChildCount(root); i++) { TreeElement child = (TreeElement) treeModel.getChild(root, i); if (child.isCategory()) { treeMovies.expandRow(i); if (select(movie, child, path.pathByAddingChild(child))) { return true; } treeMovies.collapseRow(i); } if (child instanceof Movie && ((Entity) child).getId() == movie.getId()) { treeMovies.setSelectionPath(path.pathByAddingChild(child)); return true; } } return false; } @SuppressWarnings("unchecked") private IPrincipalController<Movie, IMovieView> getMovieController() { if(movieController == null){ movieController = getBean("movieController", IPrincipalController.class); } return movieController; } @Override public void selectFirst() { if (treeModel.getChildCount(treeModel.getRoot()) > 0) { selectFirst(treeModel.getRoot(), new TreePath(treeModel.getRoot())); } } /** * Select the first movie in the tree. * * @param root The element to start the search for. * @param path The current search path. * * @return true if the first movie has been selected else false. */ private boolean selectFirst(TreeElement root, TreePath path) { for (int i = 0; i < treeModel.getChildCount(root); i++) { TreeElement child = (TreeElement) treeModel.getChild(root, i); if (child.isCategory()) { treeMovies.expandRow(i); if (selectFirst(child, path.pathByAddingChild(child))) { return true; } treeMovies.collapseRow(i); } if (child instanceof Movie) { treeMovies.setSelectionPath(path.pathByAddingChild(child)); return true; } } return false; } @Override public void refreshData() { for (MoviePanel panel : layeredPanel.getLayers()) { panel.setMovie(getModel().getCurrentMovie()); } } @Override public Movie getSelectedMovie() { return treeMovies.getSelectionPath() == null ? null : (Movie) treeMovies.getSelectionPath().getLastPathComponent(); } @Override public IMoviesModel getModel() { return (IMoviesModel) super.getModel(); } @Override public void expandAll() { treeMovies.expandAll(); } @Override public void collapseAll() { treeMovies.collapseAll(); } @Override public void resort() { displayListChanged(); } @Override public int getPosition() { return 5; } @Override public String getTitleKey() { return "data.titles.movie"; } @Override public IEditMovieView getEditMoviePanel() { return (IEditMovieView) editMoviePanel; } }