package org.sigmah.offline.view;
/*
* #%L
* Sigmah
* %%
* Copyright (C) 2010 - 2016 URD
* %%
* This program 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.
*
* This program 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 this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
import com.google.gwt.dom.client.Style;
import com.google.gwt.i18n.shared.DateTimeFormat;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.InlineHTML;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import java.util.Date;
import java.util.EnumMap;
import org.sigmah.client.i18n.I18N;
import org.sigmah.client.ui.widget.RatioBar;
import org.sigmah.offline.status.ProgressType;
/**
* Popup menu to manage the offline mode.
*
* @author Raphaƫl Calabro (rcalabro@ideia.fr)
*/
public class OfflineMenuPanel extends Composite {
private static final String MENU_ID = "offline-menu";
private static final String ACTION_STYLE = "offline-action";
private static final String UPDATE_DATABASE_ACTION_STYLE = "update-database";
private static final String TRANSFER_FILES_ACTION_STYLE = "transfert-files";
private static final String REMOVE_DATABASE_ACTION_STYLE = "delete-database";
private static final String VARIABLE_STYLE = "offline-menu-variable";
private static final String SEPARATOR_STYLE = "offline-action-separator";
private static final String PROGRESS_BAR_STYLE = "offline-menu-progress";
private static final String PROGRESS_LABEL_STYLE = "offline-menu-progress-label";
private InlineLabel sigmahUpdateVariable;
private InlineLabel databaseUpdateVariable;
private Anchor updateDatabaseAnchor;
private InlineLabel pendingUploadsVariable;
private InlineLabel pendingDownloadsVariable;
private Anchor transferFilesAnchor;
private Anchor removeOfflineDataAnchor;
private final EnumMap<ProgressType, RatioBar> bars = new EnumMap(ProgressType.class);
private final EnumMap<ProgressType, FlowPanel> wraps = new EnumMap(ProgressType.class);
private Widget[] fileBaseWidgets;
/**
* Creates a new menu.
*/
public OfflineMenuPanel() {
initWidget(createPanel());
}
/**
* Retrieves the link to update the database.
*
* @return The link to update the database.
*/
public Anchor getUpdateDatabaseAnchor() {
return updateDatabaseAnchor;
}
/**
* Retrieves the link to transfer files.
*
* @return The link to transfer files.
*/
public Anchor getTransferFilesAnchor() {
return transferFilesAnchor;
}
/**
* Retrieves the link to remove the current offline database.
*
* @return The link to remove the current offline database.
*/
public Anchor getRemoveOfflineDataAnchor() {
return removeOfflineDataAnchor;
}
/**
* Retrieves the progress bar associated with the given type.
*
* @param progressType Type of loadable element.
* @return The associated progress bar.
*/
public RatioBar getBar(ProgressType progressType) {
return bars.get(progressType);
}
/**
* Show or hide the progress bar associated with the given type.
*
* @param progressType Type of loadable element.
* @param visible <code>true</code> to show the bar, <code>false</code> to hide it.
*/
public void setBarVisible(ProgressType progressType, boolean visible) {
if(visible) {
wraps.get(progressType).getElement().getStyle().clearDisplay();
} else {
wraps.get(progressType).getElement().getStyle().setDisplay(Style.Display.NONE);
}
}
public void setSigmahUpdateDate(Date sigmahUpdateDate) {
setUpdateDate(sigmahUpdateDate, sigmahUpdateVariable);
}
public void setDatabaseUpdateDate(Date databaseUpdateDate) {
setUpdateDate(databaseUpdateDate, databaseUpdateVariable);
}
private void setUpdateDate(Date date, InlineLabel label) {
if(date != null) {
label.setText(DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_TIME_SHORT).format(date));
} else {
label.setText(I18N.CONSTANTS.offlineDatabaseLastCompleteUpdateNever());
}
}
public void setPendingsTransfers(ProgressType progressType, int pending) {
switch(progressType) {
case DOWNLOAD:
setPendingDownloads(pending);
break;
case UPLOAD:
setPendingUploads(pending);
break;
}
}
public void setPendingUploads(int pending) {
setInt(pending, pendingUploadsVariable);
}
public void setPendingDownloads(int pending) {
setInt(pending, pendingDownloadsVariable);
}
private void setInt(int value, InlineLabel label) {
label.setText(Integer.toString(value));
}
public void removeFileBaseWidgets() {
for(final Widget widget : fileBaseWidgets) {
widget.removeFromParent();
}
}
private Widget createPanel() {
final FlowPanel rootPanel = new FlowPanel();
rootPanel.getElement().setId(MENU_ID);
// Application cache status
// rootPanel.add(createHeader(I18N.CONSTANTS.offlineModeHeader(), I18N.CONSTANTS.offlineModeAvailability()));
sigmahUpdateVariable = createVariable(I18N.CONSTANTS.offlineDatabaseLastCompleteUpdateNever());
// rootPanel.add(sigmahUpdateVariable);
final RatioBar applicationCacheRatioBar = new RatioBar(0.0);
bars.put(ProgressType.APPLICATION_CACHE, applicationCacheRatioBar);
// rootPanel.add(
wrapProgressBar(I18N.CONSTANTS.offlineModeProgress(), applicationCacheRatioBar, ProgressType.APPLICATION_CACHE);
// );
//
// rootPanel.add(createSeparator(true));
// Local database status
rootPanel.add(createHeader(I18N.CONSTANTS.offlineDatabaseHeader(), I18N.CONSTANTS.offlineDatabaseLastCompleteUpdate()));
databaseUpdateVariable = createVariable(I18N.CONSTANTS.offlineDatabaseLastCompleteUpdateNever());
rootPanel.add(databaseUpdateVariable);
final RatioBar localDatabaseRatioBar = new RatioBar(0.0);
bars.put(ProgressType.DATABASE, localDatabaseRatioBar);
rootPanel.add(wrapProgressBar(I18N.CONSTANTS.offlineSynchronizeProgress(), localDatabaseRatioBar, ProgressType.DATABASE));
updateDatabaseAnchor = createActionButton(I18N.CONSTANTS.offlineActionUpdateDatabase());
updateDatabaseAnchor.addStyleName(UPDATE_DATABASE_ACTION_STYLE);
rootPanel.add(updateDatabaseAnchor);
rootPanel.add(createSeparator(false));
// File base status
final InlineHTML offlineFileBaseHeader = createHeader(I18N.CONSTANTS.offlineFileBaseHeader());
rootPanel.add(offlineFileBaseHeader);
final FlowPanel pendingUploadsPanel = new FlowPanel();
pendingUploadsPanel.add(createListEntry(I18N.CONSTANTS.offlineTransfertUploadPending()));
pendingUploadsVariable = createVariable("0");
pendingUploadsPanel.add(pendingUploadsVariable);
rootPanel.add(pendingUploadsPanel);
final RatioBar uploadRatioBar = new RatioBar(0.0);
bars.put(ProgressType.UPLOAD, uploadRatioBar);
rootPanel.add(wrapProgressBar(I18N.CONSTANTS.offlineTransfertUploadProgress(), uploadRatioBar, ProgressType.UPLOAD));
final FlowPanel pendingDownloadsPanel = new FlowPanel();
pendingDownloadsPanel.add(createListEntry(I18N.CONSTANTS.offlineTransfertDownloadPending()));
pendingDownloadsVariable = createVariable("0");
pendingDownloadsPanel.add(pendingDownloadsVariable);
rootPanel.add(pendingDownloadsPanel);
final RatioBar downloadRatioBar = new RatioBar(0.0);
bars.put(ProgressType.DOWNLOAD, downloadRatioBar);
rootPanel.add(wrapProgressBar(I18N.CONSTANTS.offlineTransfertDownloadProgress(), downloadRatioBar, ProgressType.DOWNLOAD));
transferFilesAnchor = createActionButton(I18N.CONSTANTS.offlineActionTransferFiles());
transferFilesAnchor.addStyleName(TRANSFER_FILES_ACTION_STYLE);
rootPanel.add(transferFilesAnchor);
fileBaseWidgets = new Widget[] {offlineFileBaseHeader, pendingUploadsPanel, uploadRatioBar, pendingDownloadsPanel, downloadRatioBar, transferFilesAnchor};
rootPanel.add(createSeparator(true));
// Destroy offline mode button
removeOfflineDataAnchor = createActionButton(I18N.CONSTANTS.offlineActionDestroyLocalData());
removeOfflineDataAnchor.addStyleName(REMOVE_DATABASE_ACTION_STYLE);
rootPanel.add(removeOfflineDataAnchor);
return rootPanel;
}
private InlineHTML createHeader(String header) {
return createHeader(header, null);
}
private InlineHTML createHeader(String header, String statusLabel) {
final SafeHtmlBuilder htmlBuilder = new SafeHtmlBuilder()
.appendHtmlConstant("<h1>")
.appendEscaped(header)
.appendHtmlConstant("</h1>");
if(statusLabel != null) {
htmlBuilder
.appendHtmlConstant("<span style=\"margin-left: 2em; font-style: italic\">")
.appendEscaped(statusLabel)
.appendHtmlConstant("</span>");
}
return new InlineHTML(htmlBuilder.toSafeHtml());
}
private InlineHTML createListEntry(String label) {
return new InlineHTML(new SafeHtmlBuilder()
.appendHtmlConstant("<span style=\"margin-left: 2em;\">- ")
.appendEscaped(label)
.appendHtmlConstant("</span>")
.toSafeHtml());
}
private InlineLabel createVariable(String value) {
final InlineLabel label = new InlineLabel(value);
label.setStyleName(VARIABLE_STYLE);
return label;
}
private InlineHTML createSeparator(boolean visible) {
final InlineHTML inlineHTML = new InlineHTML(new SafeHtmlBuilder()
.appendHtmlConstant("<hr class=\"" + SEPARATOR_STYLE + "\">")
.toSafeHtml());
if(!visible) {
inlineHTML.getElement().getStyle().setVisibility(Style.Visibility.HIDDEN);
}
return inlineHTML;
}
private Anchor createActionButton(String label) {
final Anchor anchor = new Anchor(label);
anchor.setStyleName(ACTION_STYLE);
return anchor;
}
private FlowPanel wrapProgressBar(String prefix, RatioBar ratioBar, ProgressType type) {
final FlowPanel panel = new FlowPanel();
final Label label = new Label(prefix);
panel.add(label);
panel.add(ratioBar);
label.setStyleName(PROGRESS_LABEL_STYLE);
ratioBar.setStyleName(PROGRESS_BAR_STYLE);
wraps.put(type, panel);
return panel;
}
}