/*
* Funambol is a mobile platform developed by Funambol, Inc.
* Copyright (C) 2010 Funambol, Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by
* the Free Software Foundation with the addition of the following permission
* added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
* WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* 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 Affero General Public License
* along with this program; if not, see http://www.gnu.org/licenses or write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA.
*
* You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite
* 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Powered by Funambol" logo. If the display of the logo is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Powered by Funambol".
*/
package de.chbosync.android.syncmlclient.activities;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.app.Dialog;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TabHost;
import android.widget.TextView;
import com.funambol.client.controller.HomeScreenController;
import com.funambol.client.localization.Localization;
import com.funambol.client.ui.Screen;
import com.funambol.util.Log;
import de.chbosync.android.syncmlclient.R;
import de.chbosync.android.syncmlclient.AndroidCustomization;
import de.chbosync.android.syncmlclient.activities.settings.AndroidAdvancedSettingsTab;
import de.chbosync.android.syncmlclient.activities.settings.AndroidSettingsTab;
import de.chbosync.android.syncmlclient.activities.settings.AndroidSyncSettingsTab;
import de.chbosync.android.syncmlclient.activities.settings.SaveSettingsCallback;
import de.chbosync.android.syncmlclient.controller.AndroidController;
import de.chbosync.android.syncmlclient.controller.AndroidHomeScreenController;
import de.chbosync.android.syncmlclient.controller.AndroidSettingsScreenController;
/**
* This is the container Activity for all the settings (Sync, Advanced).
*/
public class AndroidSettingsScreen extends Activity
implements Screen {
private static final String TAG = "AndroidSettingsScreen";
private TabHost tabs;
private Localization localization;
private AndroidCustomization customization;
private AndroidDisplayManager displayManager;
private static final String LAST_SELECTED_TAB_ID = "LastSelectedTabId";
private static final String REFRESH_DIRECTION_ALERT_PENDING = "RefreshDirectionAlert";
private static final String REFRESH_TYPE_ALERT_PENDING = "RefreshTypeAlert";
private List<AndroidSettingsTab> settingsTabList = new ArrayList<AndroidSettingsTab>();
/**
* Called with the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidController gc = AndroidController.getInstance();
this.localization = gc.getLocalization();
this.customization = (AndroidCustomization)gc.getCustomization();
this.displayManager = (AndroidDisplayManager)gc.getDisplayManager();
setContentView(R.layout.settings);
setupAllTabs(savedInstanceState);
// Init button listeners
Button saveButton = (Button)findViewById(R.id.save_button);
saveButton.setOnClickListener(new SaveListener());
Button cancelButton = (Button)findViewById(R.id.cancel_button);
cancelButton.setOnClickListener(new CancelListener());
int directionAlertId = 0;
int typeAlertId = 0;
if (savedInstanceState != null) {
directionAlertId = savedInstanceState.getInt(REFRESH_DIRECTION_ALERT_PENDING);
typeAlertId = savedInstanceState.getInt(REFRESH_TYPE_ALERT_PENDING);
}
AndroidSettingsScreenController settingsScreenController = gc.getSettingsScreenController();
settingsScreenController.setSettingsScreen(this);
//Resume the last sync dialog alert if it was displayed before
//resuming this activity
if (directionAlertId == AndroidDisplayManager.REFRESH_DIRECTION_DIALOG_ID) {
savedInstanceState.remove(REFRESH_DIRECTION_ALERT_PENDING);
gc.getDialogController().showRefreshDirectionDialog(this);
} else if (typeAlertId == AndroidDisplayManager.REFRESH_TYPE_DIALOG_ID) {
savedInstanceState.remove(REFRESH_TYPE_ALERT_PENDING);
gc.getDialogController().resumeLastRefreshTypeDialog(this);
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (Log.isLoggable(Log.TRACE)) {
Log.trace(TAG, "onSaveInstanceState");
}
// Save the current selected tab
int id = tabs.getCurrentTab();
outState.putInt(LAST_SELECTED_TAB_ID, id);
//Notifies to the Bundle resource if a selection alert is pending (For example after screen rotation)
if (displayManager.isAlertPending(AndroidDisplayManager.REFRESH_DIRECTION_DIALOG_ID)) {
displayManager.dismissSelectionDialog(AndroidDisplayManager.REFRESH_DIRECTION_DIALOG_ID);
outState.putInt(REFRESH_DIRECTION_ALERT_PENDING, AndroidDisplayManager.REFRESH_DIRECTION_DIALOG_ID);
} else if (displayManager.isAlertPending(AndroidDisplayManager.REFRESH_TYPE_DIALOG_ID)) {
displayManager.dismissSelectionDialog(AndroidDisplayManager.REFRESH_TYPE_DIALOG_ID);
outState.putInt(REFRESH_TYPE_ALERT_PENDING, AndroidDisplayManager.REFRESH_TYPE_DIALOG_ID);
}
}
public void setupAllTabs(Bundle state) {
tabs = (TabHost)this.findViewById(R.id.tabhost);
tabs.setup();
// Set the tab widget background
tabs.getTabWidget().setBackgroundResource(R.color.black);
setupSettingsTab(new AndroidSyncSettingsTab (this, state), tabs);
setupSettingsTab(new AndroidAdvancedSettingsTab(this, state), tabs);
// Select the last selected tab
int lastSelectedId = 0;
if(state != null) {
lastSelectedId = state.getInt(LAST_SELECTED_TAB_ID);
}
tabs.setCurrentTab(lastSelectedId);
}
private void setupSettingsTab(AndroidSettingsTab tab, TabHost tabs) {
if (Log.isLoggable(Log.DEBUG)) {
Log.debug(TAG, "Setting up tab: " + tab.getIndicatorLabel());
}
TabHost.TabSpec syncTabSpec = tabs.newTabSpec(tab.getTag());
syncTabSpec.setContent(tab);
syncTabSpec.setIndicator(tab.getIndicatorLabel(), tab.getIndicatorIcon());
tabs.addTab(syncTabSpec);
// If the TabWidget contains the separators, it should be doubled
int tabIndex = tabs.getTabWidget().getTabCount()-1;
// Define custom background resource for each TabWidget child
View childViewAtTabIndex = tabs.getTabWidget().getChildAt(tabIndex);
childViewAtTabIndex.setBackgroundResource(R.drawable.tab_indicator_bg);
//modified for ChBoSync to prevent crash if called from main menu/settings
if (childViewAtTabIndex instanceof RelativeLayout) {
RelativeLayout relativeLayout = (RelativeLayout) childViewAtTabIndex;
View childView = relativeLayout.getChildAt(1);
if (childView instanceof TextView) {
TextView tv = (TextView) childView;
tv.setTextAppearance(this, R.style.tab_widget);
}
} else if (childViewAtTabIndex instanceof LinearLayout) {
LinearLayout linLayout = (LinearLayout) childViewAtTabIndex;
View childView = linLayout.getChildAt(1);
if (childView instanceof TextView) {
TextView tv = (TextView) childView;
tv.setTextAppearance(this, R.style.tab_widget);
}
}
settingsTabList.add(tab);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && hasChanges()) {
// Ask to the user if he want to save settings since he did changes
displayManager.askYesNoQuestion(this, localization.getLanguage(
"settings_changed_alert"),
new Runnable() {
public void run() {
save(true, null);
}
},
new Runnable() {
public void run() {
// Shall we close the settings screen?
}
}, 0);
return false;
} else {
return super.onKeyDown(keyCode, event);
}
}
@Override
protected Dialog onCreateDialog(int id) {
if (Log.isLoggable(Log.TRACE)) {
Log.trace(TAG, "onCreateDialog: " + id);
}
Dialog result = null;
if(displayManager != null) {
result = displayManager.createDialog(id);
}
if(result != null) {
return result;
} else {
return super.onCreateDialog(id);
}
}
/**
* Save settings for all the tabs, and eventually close the screen.
*
* @param close true if the settings screen must be closed after saving
* @param callback Used to be notified when tab settings are saved
*/
public void save(boolean close, SaveSettingsCallback callback) {
if (Log.isLoggable(Log.INFO)) {
Log.info(TAG, "Saving settings");
}
AndroidController gc = AndroidController.getInstance();
AndroidHomeScreenController ahsc = (AndroidHomeScreenController)gc
.getHomeScreenController();
if (ahsc.isSynchronizing() || ahsc.isFirstSyncDialogDisplayed()){
displayManager.showMessage(this, localization.getLanguage(
"sync_in_progress_dialog_save"));
if (Log.isLoggable(Log.INFO)) {
Log.info(TAG, "Cannot save settings. Synchronization in progress...");
}
return;
}
if(callback == null) {
callback = new SaveCallback(close, settingsTabList.size());
} else {
callback.setCount(settingsTabList.size());
}
// Save the configuration for all the tabs
AndroidAdvancedSettingsTab aast = null;
boolean syncButtonsHaveToBeUpdated = false;
for(AndroidSettingsTab tab : settingsTabList) {
if (Log.isLoggable(Log.INFO)) {
Log.info(TAG, "Saving " + tab.getIndicatorLabel() + " settings");
}
boolean hasChanges = tab.hasChanges();
if(hasChanges == false) {
callback.tabSettingsSaved(false);
continue;
}
// next block was added for ChBoSync
if (tab instanceof AndroidAdvancedSettingsTab) {
aast = (AndroidAdvancedSettingsTab) tab;
if ( aast.hasShowNotesDummySyncButtonChanges() )
syncButtonsHaveToBeUpdated = true;
}
// Save the settings for this tab
tab.saveSettings(callback);
// next block was added for ChBoSync
if (syncButtonsHaveToBeUpdated == true) {
ahsc.updateSyncButtons();
syncButtonsHaveToBeUpdated = false;
}
} // for tabs
}
private class SaveCallback extends SaveSettingsCallback {
public SaveCallback(boolean close, int count) {
super(close, count);
}
@Override
public void tabSettingsSaved(boolean changes) {
super.tabSettingsSaved(changes);
if(count <= 0 && result == true) {
if (changesFound) {
displayManager.showMessage(AndroidSettingsScreen.this,
localization.getLanguage("settings_saved"));
}
if (close) {
finish();
}
}
}
}
/**
* @return true if there are changes in settings (i.e. changes for at least one of the two tab).
*/
public boolean hasChanges() {
boolean hasChanges = false;
for(AndroidSettingsTab tab : settingsTabList) {
hasChanges |= tab.hasChanges();
}
return hasChanges;
}
public Object getUiScreen() {
return this;
}
public void cancel() {
for(AndroidSettingsTab tab : settingsTabList) {
tab.cancelSettings();
}
finish();
}
/**
* A call-back for when the user presses the save button.
*/
private class SaveListener implements OnClickListener {
public void onClick(View v) {
save(true, null);
}
}
/**
* A call-back for when the user presses the cancel button.
*/
private class CancelListener implements OnClickListener {
public void onClick(View v) {
cancel();
}
}
}