/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.fps.view;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.util.Observable;
import java.util.Observer;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingConstants;
import org.openflexo.FlexoCst;
import org.openflexo.foundation.DataModification;
import org.openflexo.foundation.FlexoEditor;
import org.openflexo.foundation.FlexoModelObject;
import org.openflexo.foundation.FlexoObservable;
import org.openflexo.foundation.FlexoObserver;
import org.openflexo.foundation.ObjectDeleted;
import org.openflexo.foundation.action.FlexoActionSource;
import org.openflexo.foundation.rm.ResourceType;
import org.openflexo.fps.CVSFile;
import org.openflexo.fps.CVSFile.FileContentEditor;
import org.openflexo.fps.CVSStatus;
import org.openflexo.fps.FPSCst;
import org.openflexo.fps.action.CommitFiles;
import org.openflexo.fps.action.EditCVSFile;
import org.openflexo.fps.action.MarkAsMergedFiles;
import org.openflexo.fps.action.RevertToSavedCVSFile;
import org.openflexo.fps.action.SaveCVSFile;
import org.openflexo.fps.action.UpdateFiles;
import org.openflexo.fps.controller.FPSController;
import org.openflexo.icon.FilesIconLibrary;
import org.openflexo.icon.IconLibrary;
import org.openflexo.icon.UtilsIconLibrary;
import org.openflexo.localization.FlexoLocalization;
import org.openflexo.logging.FlexoLogger;
import org.openflexo.swing.VerticalLayout;
import org.openflexo.toolbox.ImageIconResource;
import org.openflexo.view.ModuleView;
import org.openflexo.view.controller.model.FlexoPerspective;
import org.openflexo.view.listener.FlexoActionButton;
/**
* @author sylvain
*/
public class CVSFileModuleView extends JPanel implements ModuleView<CVSFile>, FlexoObserver, FlexoActionSource, FileContentEditor, Observer {
private final Logger logger = FlexoLogger.getLogger(CVSFileModuleView.class.getPackage().getName());
protected CVSFile _cvsFile;
private final FPSController _controller;
public CVSFileModuleView(CVSFile cvsFile, FPSController controller) {
super(new BorderLayout());
_controller = controller;
_cvsFile = cvsFile;
_cvsFile.addObserver(this);
updateView(true);
}
private CVSStatus cvsStatus = CVSStatus.Unknown;
private boolean isEdited = false;
public void refresh() {
updateView(true);
}
private void updateView(boolean forceRebuild) {
if (forceRebuild || cvsStatus == CVSStatus.Unknown || cvsStatus != _cvsFile.getStatus() || isEdited != _cvsFile.isEdited()) {
logger.fine("CVSFileModuleView :" + _cvsFile.getFileName() + " rebuild view for new status " + _cvsFile.getStatus());
rebuildView();
_header.update();
revalidate();
repaint();
}
else {
if (_header != null) {
_header.update();
}
if (_codeDisplayer != null) {
_codeDisplayer.update();
}
}
}
private CodeDisplayer _codeDisplayer;
private ViewHeader _header;
public static ImageIcon bigIconForFile(CVSFile file) {
ResourceType resourceType = file.getResourceType();
return FilesIconLibrary.mediumIconForFileFormat(resourceType.getFormat());
}
protected class ViewHeader extends JPanel {
JLabel icon;
JLabel title;
JLabel subTitle;
JLabel statusIcon;
JLabel mergeStatusIcon;
JPanel titlePanel;
JPanel subTitlePanel;
JPanel mergeInfoPanel;
JLabel mergeInfo;
JPanel controlPanel;
Vector<FlexoActionButton> actionButtons = new Vector<FlexoActionButton>();
protected ViewHeader() {
super(new BorderLayout());
icon = new JLabel(bigIconForFile(_cvsFile));
icon.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
add(icon, BorderLayout.WEST);
title = new JLabel(_cvsFile.getFileName(), SwingConstants.LEFT);
// title.setVerticalAlignment(JLabel.BOTTOM);
title.setFont(FPSCst.HEADER_FONT);
title.setForeground(Color.BLACK);
title.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 5));
subTitle = new JLabel(subTitleForFile(), SwingConstants.LEFT);
// title.setVerticalAlignment(JLabel.BOTTOM);
subTitle.setFont(FPSCst.SUB_TITLE_FONT);
subTitle.setForeground(Color.GRAY);
subTitle.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 5));
titlePanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
statusIcon = new JLabel();
// statusIcon.setVerticalAlignment(JLabel.BOTTOM);
statusIcon.setBorder(BorderFactory.createEmptyBorder(10, 5, 0, 5));
titlePanel.add(statusIcon);
titlePanel.add(title);
subTitlePanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
statusIcon = new JLabel();
mergeStatusIcon = new JLabel();
mergeStatusIcon.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 5));
subTitlePanel.add(mergeStatusIcon);
subTitlePanel.add(subTitle);
mergeInfoPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
mergeInfo = new JLabel(mergeInfoForFile(), SwingConstants.LEFT);
mergeInfo.setFont(FPSCst.SUB_TITLE_FONT);
mergeInfo.setForeground(Color.BLACK);
mergeInfo.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
mergeInfoPanel.add(mergeInfo);
JPanel labelsPanel = new JPanel(new GridLayout(3, 1));
labelsPanel.add(titlePanel);
labelsPanel.add(subTitlePanel);
labelsPanel.add(mergeInfoPanel);
add(labelsPanel, BorderLayout.CENTER);
controlPanel = new JPanel(new FlowLayout());
if (isEdited) {
FlexoActionButton saveAction = new FlexoActionButton(SaveCVSFile.actionType, "save", CVSFileModuleView.this,
getController());
FlexoActionButton revertToSavedAction = new FlexoActionButton(RevertToSavedCVSFile.actionType, "revert_to_saved",
CVSFileModuleView.this, getController());
actionButtons.add(saveAction);
actionButtons.add(revertToSavedAction);
controlPanel.add(saveAction);
controlPanel.add(revertToSavedAction);
} else {
FlexoActionButton editFileAction = new FlexoActionButton(EditCVSFile.actionType, "edit", CVSFileModuleView.this,
getController());
actionButtons.add(editFileAction);
controlPanel.add(editFileAction);
if (_cvsFile.getStatus().isConflicting()) {
FlexoActionButton markAsMergedFileAction = new FlexoActionButton(MarkAsMergedFiles.actionType, "mark_as_merged",
CVSFileModuleView.this, getController());
actionButtons.add(markAsMergedFileAction);
controlPanel.add(markAsMergedFileAction);
}
if (_cvsFile.getStatus().isLocallyModified() && !_cvsFile.getStatus().isConflicting()) {
FlexoActionButton commitFileAction = new FlexoActionButton(CommitFiles.actionType, "commit", CVSFileModuleView.this,
getController());
actionButtons.add(commitFileAction);
controlPanel.add(commitFileAction);
}
if (_cvsFile.getStatus().isRemotelyModified() && !_cvsFile.getStatus().isConflicting()) {
FlexoActionButton updateFileAction = new FlexoActionButton(UpdateFiles.actionType, "update", CVSFileModuleView.this,
getController());
actionButtons.add(updateFileAction);
controlPanel.add(updateFileAction);
}
}
controlPanel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
add(controlPanel, BorderLayout.EAST);
update();
validate();
}
private void addInfoPanel(Icon icon, String titleString, String textString) {
JLabel regenerateIcon = new JLabel(icon);
JLabel title = new JLabel(titleString, SwingConstants.LEFT);
title.setFont(FlexoCst.BOLD_FONT);
JTextArea text = new JTextArea(textString);
text.setBackground(null);
text.setEditable(false);
text.setFont(FlexoCst.NORMAL_FONT);
text.setLineWrap(true);
text.setWrapStyleWord(true);
text.setBorder(BorderFactory.createEmptyBorder(5, 30, 10, 30));
JPanel infoPanel = new JPanel(new VerticalLayout());
JPanel titlePanel = new JPanel(new FlowLayout());
titlePanel.add(regenerateIcon);
titlePanel.add(title);
infoPanel.add(titlePanel);
infoPanel.add(text);
add(infoPanel, BorderLayout.SOUTH);
}
private String subTitleForFile() {
CVSStatus status = _cvsFile.getStatus();
String returned = "";
if (isEdited) {
returned = FlexoLocalization.localizedForKey("edition_of_file_on_disk");
} else {
returned = status.getLocalizedStringRepresentation();
if (_cvsFile.getStatus().isConflicting()) {
if (_cvsFile.getMerge().isResolved()) {
returned += ", " + FlexoLocalization.localizedForKey("all_conflicts_are_resolved");
} else {
returned += ", " + FlexoLocalization.localizedForKey("some_conflicts_are_still_unresolved");
}
}
}
return returned;
}
private String mergeInfoForFile() {
if (_cvsFile.getStatus().isConflicting()) {
String leftChangesIconHTML = ((ImageIconResource) UtilsIconLibrary.LEFT_MODIFICATION_ICON).getHTMLImg();
String rightChangesIconHTML = ((ImageIconResource) UtilsIconLibrary.RIGHT_MODIFICATION_ICON).getHTMLImg();
String conflictIconHTML = ((ImageIconResource) UtilsIconLibrary.CONFLICT_ICON).getHTMLImg();
return "<html>" + rightChangesIconHTML + " " + _cvsFile.getMerge().getRightChangeCount() + " " + leftChangesIconHTML
+ " " + _cvsFile.getMerge().getLeftChangeCount() + " " + conflictIconHTML + " "
+ _cvsFile.getMerge().getConflictsChangeCount() + " " + " ("
+ _cvsFile.getMerge().getResolvedConflictsChangeCount() + "/" + _cvsFile.getMerge().getConflictsChangeCount() + " "
+ FlexoLocalization.localizedForKey("resolved_plural") + ")" + "</html>";
} else if (_cvsFile.getStatus().isLocallyModified()) {
String leftRemovalIconHTML = ((ImageIconResource) UtilsIconLibrary.LEFT_ADDITION_ICON).getHTMLImg();
String leftAdditionIconHTML = ((ImageIconResource) UtilsIconLibrary.LEFT_REMOVAL_ICON).getHTMLImg();
String leftModificationIconHTML = ((ImageIconResource) UtilsIconLibrary.LEFT_MODIFICATION_ICON).getHTMLImg();
String additionAsString = "";
String removalAsString = "";
String modificationAsString = "";
if (_codeDisplayer instanceof DiffCodeDisplayer) {
additionAsString = "" + ((DiffCodeDisplayer) _codeDisplayer).getAdditionChangeCount();
removalAsString = "" + ((DiffCodeDisplayer) _codeDisplayer).getRemovalChangeCount();
modificationAsString = "" + ((DiffCodeDisplayer) _codeDisplayer).getModificationChangeCount();
} else {
additionAsString = "?";
removalAsString = "?";
modificationAsString = "?";
}
return "<html>" + leftModificationIconHTML + " " + modificationAsString + " " + leftAdditionIconHTML + " "
+ additionAsString + " " + leftRemovalIconHTML + " " + removalAsString + "</html>";
} else if (_cvsFile.getStatus().isRemotelyModified()) {
String rightAdditionIconHTML = ((ImageIconResource) UtilsIconLibrary.RIGHT_ADDITION_ICON).getHTMLImg();
String rightRemovalIconHTML = ((ImageIconResource) UtilsIconLibrary.RIGHT_REMOVAL_ICON).getHTMLImg();
String rightModificationIconHTML = ((ImageIconResource) UtilsIconLibrary.RIGHT_MODIFICATION_ICON).getHTMLImg();
String additionAsString = "";
String removalAsString = "";
String modificationAsString = "";
if (_codeDisplayer instanceof DiffCodeDisplayer) {
additionAsString = "" + ((DiffCodeDisplayer) _codeDisplayer).getAdditionChangeCount();
removalAsString = "" + ((DiffCodeDisplayer) _codeDisplayer).getRemovalChangeCount();
modificationAsString = "" + ((DiffCodeDisplayer) _codeDisplayer).getModificationChangeCount();
} else {
additionAsString = "?";
removalAsString = "?";
modificationAsString = "?";
}
return "<html>" + rightModificationIconHTML + " " + modificationAsString + " " + rightAdditionIconHTML + " "
+ additionAsString + " " + rightRemovalIconHTML + " " + removalAsString + "</html>";
} else {
return "";
}
}
protected void update() {
title.setText(_cvsFile.getFileName());
if (statusIcon.getIcon() == null) {
titlePanel.add(statusIcon, 0);
}
statusIcon.setIcon(iconForStatus());
statusIcon.setBorder(BorderFactory.createEmptyBorder(10, 5, 0, 0));
if (statusIcon.getIcon() == null) {
titlePanel.remove(statusIcon);
}
if (mergeStatusIcon.getIcon() == null) {
subTitlePanel.add(mergeStatusIcon, 0);
}
mergeStatusIcon.setIcon(iconForMergeStatus());
mergeStatusIcon.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 5));
if (mergeStatusIcon.getIcon() == null) {
subTitlePanel.remove(mergeStatusIcon);
}
subTitle.setText(subTitleForFile());
mergeInfo.setText(mergeInfoForFile());
for (FlexoActionButton button : actionButtons) {
button.update();
}
}
private Icon iconForStatus() {
if (_cvsFile.getStatus() == CVSStatus.UpToDate) {
return null;
} else if (_cvsFile.getStatus() == CVSStatus.LocallyModified) {
return UtilsIconLibrary.LEFT_MODIFICATION_ICON;
} else if (_cvsFile.getStatus() == CVSStatus.MarkedAsMerged) {
return UtilsIconLibrary.LEFT_MODIFICATION_ICON;
} else if (_cvsFile.getStatus() == CVSStatus.LocallyAdded) {
return UtilsIconLibrary.LEFT_ADDITION_ICON;
} else if (_cvsFile.getStatus() == CVSStatus.LocallyRemoved) {
return UtilsIconLibrary.LEFT_REMOVAL_ICON;
} else if (_cvsFile.getStatus() == CVSStatus.RemotelyModified) {
return UtilsIconLibrary.RIGHT_MODIFICATION_ICON;
} else if (_cvsFile.getStatus() == CVSStatus.RemotelyAdded) {
return UtilsIconLibrary.RIGHT_ADDITION_ICON;
} else if (_cvsFile.getStatus() == CVSStatus.RemotelyRemoved) {
return UtilsIconLibrary.RIGHT_REMOVAL_ICON;
} else if (_cvsFile.getStatus() == CVSStatus.Conflicting) {
return UtilsIconLibrary.CONFLICT_ICON;
} else if (_cvsFile.getStatus() == CVSStatus.ConflictingAdded) {
return UtilsIconLibrary.CONFLICT_ADDITION_ICON;
} else if (_cvsFile.getStatus() == CVSStatus.ConflictingRemoved) {
return UtilsIconLibrary.CONFLICT_REMOVAL_ICON;
} else {
return IconLibrary.QUESTION_ICON;
}
}
private Icon iconForMergeStatus() {
if (_cvsFile.getStatus().isConflicting()) {
if (_cvsFile.getMerge().isResolved()) {
return UtilsIconLibrary.ACCEPT_ICON;
} else {
return UtilsIconLibrary.REFUSE_ICON;
}
} else {
return null;
}
}
}
private Observable observedMerged = null;
private void rebuildView() {
if (observedMerged != null) {
observedMerged.deleteObserver(this);
observedMerged = null;
}
removeAll();
isEdited = _cvsFile.isEdited();
_header = new ViewHeader();
add(_header, BorderLayout.NORTH);
validate();
cvsStatus = _cvsFile.getStatus();
_codeDisplayer = null;
if (isEdited) {
_codeDisplayer = new CodeEditor(_cvsFile, _controller);
_codeDisplayer.getComponent().validate();
add(_codeDisplayer.getComponent());
validate();
_codeDisplayer.getComponent().requestFocusInWindow();
}
else {
if (_cvsFile.getStatus().isConflicting()) {
_codeDisplayer = new MergeCodeDisplayer(_cvsFile, _controller);
add(_codeDisplayer.getComponent());
observedMerged = (Observable) _cvsFile.getMerge();
observedMerged.addObserver(this);
}
else if (_cvsFile.getStatus().isLocallyModified() || _cvsFile.getStatus().isRemotelyModified()) {
_codeDisplayer = new DiffCodeDisplayer(_cvsFile, _controller);
add(_codeDisplayer.getComponent());
}
else if (_cvsFile.getStatus().isUpToDate()) {
_codeDisplayer = new CodeDisplayer(_cvsFile, _controller);
add(_codeDisplayer.getComponent());
}
else {
logger.warning("I should not come here !");
}
validate();
}
}
public FPSController getController() {
return _controller;
}
@Override
public void update(FlexoObservable observable, DataModification dataModification) {
if (dataModification instanceof ObjectDeleted) {
deleteModuleView();
return;
}
if (logger.isLoggable(Level.FINE)) {
logger.fine("CGFileModuleView : RECEIVED " + dataModification + " for " + observable);
}
updateView(true);
}
@Override
public void update(Observable observable, Object dataModification) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("CGFileModuleView : RECEIVED " + dataModification + " for " + observable);
}
updateView(false);
getController().getFooter().refresh();
}
@Override
public void deleteModuleView() {
if (logger.isLoggable(Level.FINE)) {
logger.fine("CVSFileModuleView view deleted");
}
getController().removeModuleView(this);
_cvsFile.deleteObserver(this);
}
@Override
public FlexoPerspective getPerspective() {
return _controller.getCurrentPerspective();
}
@Override
public CVSFile getRepresentedObject() {
return _cvsFile;
}
@Override
public void willHide() {
// TODO Auto-generated method stub
}
@Override
public void willShow() {
// TODO Auto-generated method stub
}
/**
* Returns flag indicating if this view is itself responsible for scroll management When not, Flexo will manage it's own scrollbar for
* you
*
* @return
*/
@Override
public boolean isAutoscrolled() {
// Only exception panel requires Flexo scroll scheme
// Other panels are autonomous
return true;
}
@Override
public FlexoModelObject getFocusedObject() {
return getRepresentedObject();
}
@Override
public Vector getGlobalSelection() {
return null;
}
@Override
public String getEditedContent() {
if (isEdited) {
return ((FileContentEditor) _codeDisplayer).getEditedContent();
}
logger.warning("getEditedContent() called for a non edited file");
return null;
}
@Override
public void setEditedContent(CVSFile file) {
if (isEdited) {
((FileContentEditor) _codeDisplayer).setEditedContent(file);
} else {
logger.warning("setEditedContent() called for a non edited file");
}
}
@Override
public FlexoEditor getEditor() {
return _controller.getEditor();
}
}