/*
* ClientStateValue.java
*
* Copyright (C) 2009-12 by RStudio, Inc.
*
* Unless you have received this program directly from RStudio pursuant
* to the terms of a commercial license agreement with RStudio, then
* this program is licensed to you under the terms of version 3 of the
* GNU Affero General Public License. This program is distributed WITHOUT
* ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
* AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
*
*/
package org.rstudio.studio.client.workbench.model.helper;
import org.rstudio.core.client.Debug;
import org.rstudio.core.client.js.JsObject;
import org.rstudio.studio.client.RStudioGinjector;
import org.rstudio.studio.client.application.events.EventBus;
import org.rstudio.studio.client.workbench.events.SaveClientStateEvent;
import org.rstudio.studio.client.workbench.events.SaveClientStateHandler;
import org.rstudio.studio.client.workbench.model.ClientInitState;
import org.rstudio.studio.client.workbench.model.ClientState;
import org.rstudio.studio.client.workbench.model.ValueChangeTracker;
/**
* ClientStateValue makes it easy to hook a single value up to the ClientState
* system. Subclass one of the type-specific abstract subclasses, and provide
* implementations for onInit(T) and getValue().
*
* By default, getValue() will be called periodically to check for changes.
* This will be called quite often so if it will be expensive and there's a
* cheaper way to determine if the value changed, you can override hasChanged()
* and have different logic.
*
* @param <T>
*/
public abstract class ClientStateValue<T> implements SaveClientStateHandler
{
protected ClientStateValue(String group,
String name,
int persist,
ClientInitState state)
{
this(group, name, persist, state, false);
}
/**
* If delayedInit == true, finishInit(ClientInitState) must be called
* by the subclasser or caller, in order to complete object creation.
*/
protected ClientStateValue(String group,
String name,
int persist,
ClientInitState state,
boolean delayedInit)
{
group_ = group;
name_ = name;
persist_ = persist;
if (!delayedInit)
finishInit(state);
}
protected void finishInit(ClientInitState state)
{
JsObject grp = state.peek(group_);
T obj = doGet(grp, name_);
valueTracker_ = new ValueChangeTracker<T>(obj);
onInit(obj);
EventBus evt = RStudioGinjector.INSTANCE.getEventBus();
evt.addHandler(SaveClientStateEvent.TYPE, this);
}
protected abstract T doGet(JsObject group, String name);
protected abstract void doSet(ClientState state,
String group,
String name,
T value,
int persist);
protected abstract void onInit(T value);
protected abstract T getValue();
public final void onSaveClientState(SaveClientStateEvent event)
{
try
{
if (hasChanged())
{
ClientState clientState = event.getState();
put(clientState, getValue());
}
}
catch (Exception e)
{
Debug.log(e.toString());
}
}
protected boolean hasChanged()
{
return valueTracker_.checkForChange(getValue());
}
protected void put(ClientState clientState, T newValue)
{
doSet(clientState, group_, name_, newValue, persist_);
}
private ValueChangeTracker<T> valueTracker_;
private String group_;
private String name_;
private int persist_;
}