How to handle situations where a custom SherlockDialogFragment onCreateView() needs the activity to build its view?
More specifically, needs the activity onCreate() method to be executed before building its view. The custom SherlockDialogFragment is EffectSettingsDialog.
I can always reproduce the exception (that i mentioned in the comment section) in the emulator (tested with api level 10).
When the dialog is shown if I press ctrl-f11 (or ctrl-f12) the app crashes.
The app is thought to work in landscape mode (so I set android:screenOrientation="landscape" in the app manifest).
EffectSettingsDialog.java
/**
*
* #author
*
*/
public class EffectSettingsDialog extends SherlockDialogFragment
{
final static String DIALOG_TAG = "effect_settings_dialog";
final int UNKNOWN_BUTTON = 0;
final int OK_BUTTON = 1;
final int CANCEL_BUTTON = 2;
final int RESET_BUTTON = 3;
int pressed_button = UNKNOWN_BUTTON;
/**
*
*/
public EffectSettingsDialog( )
{
super();
CLog.i( "EffectSettingsDialog", "EffectSettingsDialog()" );
}
/**
* Create a new instance of WelcomeDialog.
*/
static EffectSettingsDialog newInstance()
{
EffectSettingsDialog d = new EffectSettingsDialog();
return d;
}
/**
*
*/
static boolean showNewInstance( FragmentActivity activity, int fx_id )
{
if ( fx_id == -1 )
return false;
Fragment prev = activity.getSupportFragmentManager().findFragmentByTag( EffectSettingsDialog.DIALOG_TAG );
if (prev != null)
return false;
EffectSettingsDialog d = EffectSettingsDialog.newInstance();
// Supply fx_id parameter to the fragment
Bundle args = new Bundle();
args.putInt( "fx_id", fx_id );
d.setArguments(args);
d.show( activity.getSupportFragmentManager(), EffectSettingsDialog.DIALOG_TAG );
return true;
}
#Override
public void onCreate( Bundle savedInstanceState )
{
CLog.i( "EffectSettingsDialog", "onCreate()" );
super.onCreate(savedInstanceState);
int style = SherlockDialogFragment.STYLE_NO_TITLE;
int theme = getTheme();
setStyle(style, theme );//, theme);
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceStateBundle )
{
CLog.i( "EffectSettingsDialog", "onCreateDialog()" );
// TODO Auto-generated method stub
Dialog d = super.onCreateDialog( savedInstanceStateBundle );
return d;
}
#Override
public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState )
{
CLog.i( "EffectSettingsDialog", "onCreateView()" );
/// Here i need to call ((MyActivity)getActivity()).getData() to properly initialize the view. Initialization code omitted...
getDialog().getWindow().setBackgroundDrawableResource( R.color.transparent );//translucent_black );
getDialog().getWindow().clearFlags( WindowManager.LayoutParams.FLAG_DIM_BEHIND );
return v;
}
}
In the activity (in the onClick() method), i use the following code:
EffectSettingsDialog.showNewInstance( this, fx_id );
This happens when the user touches a specific button.
Related
I am making a fragment that uses content provider to get contacts from any phone using listview
#SuppressWarnings("ALL")
public abstract class fragment3 extends Fragment implements
LoaderManager.LoaderCallbacks<Cursor>,
AdapterView.OnItemClickListener, androidx.loader.app.LoaderManager.LoaderCallbacks<Cursor> {
**strong text**
private LifecycleOwner owner;
private RVAdapter myadapter;
private Object CursorLoader;
public fragment3() {
}
public Loader<Cursor> loader;
private Cursor cursor;
public abstract class LoaderManager{}
ListView contactsList;
long contactId;
String contactKey;
Uri contactUri;
SimpleCursorAdapter cursorAdapter;
private final static int[] TO_IDS = {
android.R.id.text1
};
// The column index for the _ID column
final int CONTACT_ID_INDEX = 0;
// The column index for the CONTACT_KEY column
final int CONTACT_KEY_INDEX = 1;
#Override
public void onCreate(Bundle savedInstanceState) {
// Always call the super method first
super.onCreate(savedInstanceState);
// Initializes the loader
getLoaderManager().initLoader(0, null, this);}
#SuppressLint("ResourceType")
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Set the item click listener to be the current fragment.
contactsList.setOnItemClickListener(this);
// We have a menu item to show in action bar.
setHasOptionsMenu(true);
// Gets the ListView from the View list of the parent activity
contactsList =
(ListView) getActivity().findViewById(R.layout.list_view);
// Gets a CursorAdapter
cursorAdapter = new SimpleCursorAdapter(
getActivity(),
R.layout.list_item,
null,
FROM_COLUMNS, TO_IDS,
0);
// Sets the adapter for the ListView
contactsList.setAdapter(cursorAdapter);
getLoaderManager().initLoader(0, null, this);
}
// If non-null, this is the current filter the user has provided.
static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts.CONTACT_STATUS,
ContactsContract.Contacts.PHOTO_ID,
};
// Called just before the Fragment displays its UI
#Override
public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) {
/*
* Makes search string into pattern and
* stores it in the selection array
*/
selectionArgs[0] = "%" + searchString + "%";
// Starts the query
return new CursorLoader(
getActivity(),
ContactsContract.Contacts.CONTENT_URI,
PROJECTION,
SELECTION,
selectionArgs,
null
);
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
// Put the result Cursor in the adapter for the ListView
cursorAdapter.swapCursor(cursor);
}
// Defines the text expression
#SuppressLint("InlinedApi")
final String SELECTION =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ?
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY + " LIKE ?" :
ContactsContract.Contacts.DISPLAY_NAME + " LIKE ?";
// Defines a variable for the search string
private String searchString;
// Defines the array to hold values that replace the ?
private String[] selectionArgs = {searchString};
/*
* Defines an array that contains column names to move from
* the Cursor to the ListView.
*/
#SuppressLint("InlinedApi")
private final static String[] FROM_COLUMNS = {
Build.VERSION.SDK_INT
>= Build.VERSION_CODES.HONEYCOMB ?
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY :
ContactsContract.Contacts.DISPLAY_NAME
};
#Override
public void onItemClick(
AdapterView<?> parent, View item, int position, long rowID) {
// Get the Cursor
//Cursor cursor = parent.getAdapter().getCursor();
Cursor c = ((CursorAdapter)((parent)).getAdapter()).getCursor();
// Move to the selected contact
cursor.moveToPosition(position);
// Get the _ID value
contactId = cursor.getLong(CONTACT_ID_INDEX);
// Get the selected LOOKUP KEY
contactKey = cursor.getString(CONTACT_KEY_INDEX);
// Create the contact's content Uri
String mContactKey = "";
contactUri = ContactsContract.Contacts.getLookupUri(contactId, mContactKey);
/*
* You can use contactUri as the content URI for retrieving
* the details for a contact.
*/
}
// A UI Fragment must inflate its View
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the fragment layout
return inflater.inflate(R.layout.fragment_fragment3,
container, false);
}
#SuppressLint("InlinedApi") final String[] PROJECTION =
{
ContactsContract.Contacts._ID,
ContactsContract.Contacts.LOOKUP_KEY,
Build.VERSION.SDK_INT
>= Build.VERSION_CODES.HONEYCOMB ?
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY :
ContactsContract.Contacts.DISPLAY_NAME
};
#Override
public void onLoaderReset(#NonNull androidx.loader.content.Loader<Cursor> loader) {
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
}
}
I have a ListFragment that is called from a ListActivity, with a dual fragment layout on a tablet.
I have used the standard MasterDetail Fragment setup from Android Studio 0.3.6 API 19.
MyListFragment looks as follows:
import android.app.Activity;
import android.content.ContentUris;
import android.net.Uri;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.ActionMode;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import android.support.v4.widget.SimpleCursorAdapter;
import com.supascale.supascale.contentprovider.SupaScaleContentProvider;
import com.supascale.supascale.database.SupascaleDb;
/**
* A list fragment representing a list of Animals. This fragment
* also supports tablet devices by allowing list items to be given an
* 'activated' state upon selection. This helps indicate which item is
* currently being viewed in a {#link AnimalDetailFragment}.
* <p>
* Activities containing this fragment MUST implement the {#link Callbacks}
* interface.
*
* You can create new ones via the ActionBar entry "Insert".
* You can delete existing ones via a long press on the item.
*/
public class AnimalListFragment extends ListFragment implements
android.support.v4.app.LoaderManager.LoaderCallbacks<Cursor>{
private static final int ACTIVITY_CREATE = 0;
private static final int ACTIVITY_EDIT = 1;
private static final int DELETE_ID = Menu.FIRST + 1;
private SimpleCursorAdapter adapter;
protected Object mActionMode;
private ActionMode.Callback mActionModeCallback;
/**
* The serialization (saved instance state) Bundle key representing the
* activated item position. Only used on tablets.
*/
private static final String STATE_ACTIVATED_POSITION = "activated_position";
/**
* The fragment's current callback object, which is notified of list item
* clicks.
*/
private Callbacks mCallbacks = sDummyCallbacks;
/**
* The current activated item position. Only used on tablets.
*/
private int mActivatedPosition = ListView.INVALID_POSITION;
/**
* A callback interface that all activities containing this fragment must
* implement. This mechanism allows activities to be notified of item
* selections. NB AJW
*/
public interface Callbacks {
/**
* Callback for when an item has been selected.
*/
public void onItemSelected(Uri id);
}
/**
* A dummy implementation of the {#link Callbacks} interface that does
* nothing. Used only when this fragment is not attached to an activity.
*/
private static Callbacks sDummyCallbacks = new Callbacks() {
#Override
public void onItemSelected(Uri animalUri) {
}
};
/**
* Mandatory empty constructor for the fragment manager to instantiate the
* fragment (e.g. upon screen orientation changes).
*/
public AnimalListFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// super.onCreate(savedInstanceState);
return inflater.inflate(R.layout.animal_list, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
String[] from = new String[] { SupascaleDb.KEY_Animal_ANIMALIDENTIFICATION };
// Fields on the UI to which we map
int[] to = new int[] { R.id.label };
getLoaderManager().initLoader(0, null, this);
adapter = new SimpleCursorAdapter(getActivity(), R.layout.animal_row, null, from,
to, 0);
setListAdapter(adapter);
// Restore the previously serialized activated item position.
if (savedInstanceState != null
&& savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) {
setActivatedPosition(savedInstanceState.getInt(STATE_ACTIVATED_POSITION));
}
mActionModeCallback = new ActionMode.Callback() {
// Called when the action mode is created; startActionMode() was called
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Inflate a menu resource providing context menu items
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.listmenu, menu);
return true;
}
// Called each time the action mode is shown. Always called after onCreateActionMode, but
// may be called multiple times if the mode is invalidated.
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false; // Return false if nothing is done
}
// Called when the user selects a contextual menu item
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case DELETE_ID:
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item
.getMenuInfo();
Uri uri = Uri.parse(SupaScaleContentProvider.CONTENT_URI_ANIMAL + "/"
+ info.id);
getActivity().getContentResolver().delete(uri, null, null);
mode.finish(); // Action picked, so close the CAB
return true;
default:
return false;
}
}
// Called when the user exits the action mode
#Override
public void onDestroyActionMode(ActionMode mode) {
mActionMode = null;
}
};
getView().setOnLongClickListener( new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
if (mActionMode != null) {
return false;
}
// Start the CAB using the ActionMode.Callback defined above
mActionMode = view.startActionMode(mActionModeCallback);
view.setSelected(true);
return true;
}
});
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Activities containing this fragment must implement its callbacks.
if (!(activity instanceof Callbacks)) {
throw new IllegalStateException("Activity must implement fragment's callbacks.");
}
mCallbacks = (Callbacks) activity;
}
#Override
public void onDetach() {
super.onDetach();
// Reset the active callbacks interface to the dummy implementation.
mCallbacks = sDummyCallbacks;
}
#Override
public void onListItemClick(ListView listView, View view, int position, long id) {
super.onListItemClick(listView, view, position, id);
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
//2013-11-26 AJW Append the clicked item's row ID with the content provider Uri
Uri animalUri = ContentUris.withAppendedId(SupaScaleContentProvider.CONTENT_URI_ANIMAL, id);
// Send the event and Uri to the host activity
mCallbacks.onItemSelected(animalUri);
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mActivatedPosition != ListView.INVALID_POSITION) {
// Serialize and persist the activated item position.
outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition);
}
}
/**
* Turns on activate-on-click mode. When this mode is on, list items will be
* given the 'activated' state when touched.
*/
public void setActivateOnItemClick(boolean activateOnItemClick) {
// When setting CHOICE_MODE_SINGLE, ListView will automatically
// give items the 'activated' state when touched.
getListView().setChoiceMode(activateOnItemClick
? ListView.CHOICE_MODE_SINGLE
: ListView.CHOICE_MODE_NONE);
}
private void setActivatedPosition(int position) {
if (position == ListView.INVALID_POSITION) {
getListView().setItemChecked(mActivatedPosition, false);
} else {
getListView().setItemChecked(position, true);
}
mActivatedPosition = position;
}
/**
* Creates a new loader after the initLoader () call
*/
//#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String[] projection = { SupascaleDb.KEY_ROWID, SupascaleDb.KEY_Animal_ANIMALIDENTIFICATION };
CursorLoader cursorLoader = new CursorLoader(getActivity(),
SupaScaleContentProvider.CONTENT_URI_ANIMAL, projection, null, null, null);
return cursorLoader;
}
//#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
adapter.swapCursor(data);
}
//#Override
public void onLoaderReset(Loader<Cursor> loader) {
// data is not available anymore, delete reference
adapter.swapCursor(null);
}
}
My AnimalListActivity looks as follows:
/**
* An activity representing a list of Animals. This activity
* has different presentations for handset and tablet-size devices. On
* handsets, the activity presents a list of items, which when touched,
* lead to a {#link AnimalDetailActivity} representing
* item details. On tablets, the activity presents the list of items and
* item details side-by-side using two vertical panes.
* <p>
* The activity makes heavy use of fragments. The list of items is a
* {#link AnimalListFragment} and the item details
* (if present) is a {#link AnimalDetailFragment}.
* <p>
* This activity also implements the required
* {#link AnimalListFragment.Callbacks} interface
* to listen for item selections.
*/
public class AnimalListActivity extends FragmentActivity
implements AnimalListFragment.Callbacks {
/**
* Whether or not the activity is in two-pane mode, i.e. running on a tablet
* device.
*/
private boolean mTwoPane;
private SimpleCursorAdapter adapter;
private static final int ACTIVITY_CREATE = 0;
private static final int ACTIVITY_EDIT = 1;
private static final int DELETE_ID = Menu.FIRST + 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_animal_list);
if (findViewById(R.id.animal_detail_container) != null) {
// The detail container view will be present only in the
// large-screen layouts (res/values-large and
// res/values-sw600dp). If this view is present, then the
// activity should be in two-pane mode.
mTwoPane = true;
// In two-pane mode, list items should be given the
// 'activated' state when touched.
((AnimalListFragment) getSupportFragmentManager()
.findFragmentById(R.id.animal_list))
.setActivateOnItemClick(true);
}
// TODO: If exposing deep links into your app, handle intents here.
}
/**
* Callback method from {#link AnimalListFragment.Callbacks}
* indicating that the item with the given ID was selected.
*/
#Override
public void onItemSelected(Uri animalUri) {
//String id = Long.toString(ContentUris.parseId(animalUri));
if (mTwoPane) {
// In two-pane mode, show the detail view in this activity by
// adding or replacing the detail fragment using a
// fragment transaction.
Bundle arguments = new Bundle();
arguments.putString(AnimalDetailFragment.ARG_URI, animalUri.toString()); //Key value pair Adrian "animal_uri = .."
AnimalDetailFragment fragment = new AnimalDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.replace(R.id.animal_detail_container, fragment)
.commit();
} else {
// In single-pane mode, simply start the detail activity
// for the selected item ID.
Intent detailIntent = new Intent(this, AnimalDetailActivity.class);
//Uri todoUri = Uri.parse(SupaScaleContentProvider.CONTENT_URI_ANIMAL + "/" + id);
//detailIntent.putExtra(AnimalDetailFragment.ARG_ITEM_ID, id);
//startActivity(detailIntent);
detailIntent.putExtra(SupaScaleContentProvider.CONTENT_ITEM_TYPE, animalUri);
// Activity returns an result if called with startActivityForResult
startActivityForResult(detailIntent, ACTIVITY_EDIT);
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.listmenu, menu);
return true;
}
// Reaction to the menu selection
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.insert:
createAnimal();
return true;
}
return super.onOptionsItemSelected(item);
}
private void createAnimal() {
if (mTwoPane) {
// In two-pane mode, show the detail view in this activity by
// adding or replacing the detail fragment using a
// fragment transaction.
Bundle arguments = new Bundle();
//arguments.putString(AnimalDetailFragment.ARG_URI, animalUri.toString()); //Key value pair Adrian "animal_uri = .."
AnimalDetailFragment fragment = new AnimalDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.replace(R.id.animal_detail_container, fragment)
.commit();
} else {
// In single-pane mode, simply start the detail activity
Intent i = new Intent(this, AnimalDetailActivity.class);
startActivityForResult(i, ACTIVITY_EDIT);
}
}
}
AnimalListActivity.xml
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/animal_list"
android:name="com.supascale.supascale.AnimalListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
tools:context=".AnimalListActivity"
tools:layout="#android:layout/list_content" />
The List.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#android:id/list" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="No Animal Data"
android:id="#android:id/empty" />
</LinearLayout>
The row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="#+id/icon"
android:layout_width="30dp"
android:layout_height="24dp"
android:layout_marginLeft="4dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:src="#drawable/reminder" >
</ImageView>
<TextView
android:id="#+id/label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:lines="1"
android:text="#+id/textViewNormalTotal"
android:textSize="24sp"
>
</TextView>
</LinearLayout>
The fragment list scrolls correctly, and when clicked the detail fragment is correctly populated. When I long click, nothing happens, and when I release the longclick, the click event is fired.
I need for the long click to result in the CAB (Context Action Bar) to display, so that I can delete a record, or share a record etc.
mActionMode = view.startActionMode(mActionModeCallback); just never appears to be called.
Hope I have been clear enough.
Regards
Adrian
I edited and added the imports for the ListFragment, as it may have to do with support.v4?
Ok, so I did not understand the CAB help so nicely.
http://developer.android.com/guide/topics/ui/menus.html#CAB
For a ListView or ListFragment, and not another kind of view, you must use the setOnItemLongClickListener,
and not the setOnLongClickListener, as in the help from developer.android.com.
The setOnLongClickListener, is never activated by the listview, and thus never can procede to create the CAB.
I removed the following code:
getView().setOnLongClickListener( new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
if (mActionMode != null) {
return false;
}
// Start the CAB using the ActionMode.Callback defined above
mActionMode = view.startActionMode(mActionModeCallback);
view.setSelected(true);
return true;
}
});
and replaced with the following:
getListView().setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> arg0, View view,
int position, long id) {
if (mActionMode != null) {
return false;
}
Animal_id = id;
// Start the CAB using the ActionMode.Callback defined above
mActionMode = getActivity().startActionMode(mActionModeCallback);
view.setSelected(true);
return true;
}
});
Now the long click event fires, and I can get the CAB to display properly.
I have a netbeans RCP application that shows a set of nodes in the explorertopcomponent. When selected, I display details on the editortopcomponent and it works well. When I show a dialog using JOptionPage on the editor, the selected node in the tree is deselected, and eventually my editortopcomponent also loses the selected node details. Is there a way to save the selected node in the tree from being deselected if a dialog opens?
Thanks.
it is simple.
In your explorertopcomponent you have LookupListner, that "is waiting" on event "someYourNodeClass" (for example Album)appears in the lookup. You must removeLookupListener, when your explorertopcomponent is not visible or yust do nothing.
/**
* your explorertopcomponent
*/
#ConvertAsProperties(
dtd = "-//com.galileo.netbeans.module//Y//EN",
autostore = false)
#TopComponent.Description(
preferredID = "YTopComponent",
//iconBase="SET/PATH/TO/ICON/HERE",
persistenceType = TopComponent.PERSISTENCE_ALWAYS)
#TopComponent.Registration(mode = "explorer", openAtStartup = false)
#ActionID(category = "Window", id = "com.galileo.netbeans.module.YTopComponent")
#ActionReference(path = "Menu/Window" /*, position = 333 */)
#TopComponent.OpenActionRegistration(
displayName = "#CTL_YAction",
preferredID = "YTopComponent")
#Messages({
"CTL_YAction=Y",
"CTL_YTopComponent=Y Window",
"HINT_YTopComponent=This is a Y window"
})
public final class YTopComponent extends TopComponent implements LookupListener {
private Lookup.Result<Album> result;
public YTopComponent() {
initComponents();
setName(Bundle.CTL_YTopComponent());
setToolTipText(Bundle.HINT_YTopComponent());
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 400, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 300, Short.MAX_VALUE)
);
}// </editor-fold>
// Variables declaration - do not modify
// End of variables declaration
#Override
public void componentOpened() {
result = Utilities.actionsGlobalContext().lookupResult(Album.class);
result.addLookupListener(this);
}
#Override
public void componentClosed() {
result.removeLookupListener(this);
}
void writeProperties(java.util.Properties p) {
// better to version settings since initial version as advocated at
// http://wiki.apidesign.org/wiki/PropertyFiles
p.setProperty("version", "1.0");
// TODO store your settings
}
void readProperties(java.util.Properties p) {
String version = p.getProperty("version");
// TODO read your settings according to their version
}
public void resultChanged(LookupEvent le) {
Collection<? extends Album> allInstances = result.allInstances();
TopComponent findTopComponent = WindowManager.getDefault().findTopComponent("YourNodeExplorerWindow");
if (findTopComponent == null) {
return;
}
if (!findTopComponent.isShowing()) {
return;
}
if (!allInstances.isEmpty()) {
showDetail(allInstances.iterator().next());
}
}
}
Jirka
I'm using GWT 2.4. I have a TabLayoutPanel to which I add tabs. Each tab contains a ScrollPanel. My question is, how do I make the tabs in the tab bar wrap to the next line if the width of the tab bar exceeds the visible width?
Thanks, - Dave
GWT's TabLayoutPanel intentionally never wraps tabs. See lines 246-248 in TabLayoutPanel.java - (line 217 defines private static final int BIG_ENOUGH_TO_NOT_WRAP = 16384). You might be able to override this, but as #milan says, it's probably not good design.
Having multiple lines is, indeed, not recommended...
However, to be able to navigate left/right on a single tab bar with many tabs, you can use this recipe:
http://devnotesblog.wordpress.com/2010/06/17/scrollable-gwt-tablayoutpanel/
And an updated implementation that doesn't use the deprecated DeferredCommand:
package whatever.you.want;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.LayoutPanel;
import com.google.gwt.user.client.ui.TabLayoutPanel;
import com.google.gwt.user.client.ui.Widget;
/**
* A {#link TabLayoutPanel} that shows scroll buttons if necessary
*/
public class ScrolledTabLayoutPanel extends TabLayoutPanel {
private static final int IMAGE_PADDING_PIXELS = 4;
private LayoutPanel panel;
private FlowPanel tabBar;
private Image scrollLeftButton;
private Image scrollRightButton;
private HandlerRegistration windowResizeHandler;
private ImageResource leftArrowImage;
private ImageResource rightArrowImage;
public ScrolledTabLayoutPanel(double barHeight, Unit barUnit,
ImageResource leftArrowImage, ImageResource rightArrowImage) {
super(barHeight, barUnit);
this.leftArrowImage = leftArrowImage;
this.rightArrowImage = rightArrowImage;
// The main widget wrapped by this composite, which is a LayoutPanel with the tab bar & the tab content
panel = (LayoutPanel) getWidget();
// Find the tab bar, which is the first flow panel in the LayoutPanel
for (int i = 0; i < panel.getWidgetCount(); ++i) {
Widget widget = panel.getWidget(i);
if (widget instanceof FlowPanel) {
tabBar = (FlowPanel) widget;
break; // tab bar found
}
}
initScrollButtons();
}
#Override
public void add(Widget child, Widget tab) {
super.add(child, tab);
checkIfScrollButtonsNecessary();
}
#Override
public boolean remove(Widget w) {
boolean b = super.remove(w);
checkIfScrollButtonsNecessary();
return b;
}
#Override
protected void onLoad() {
super.onLoad();
if (windowResizeHandler == null) {
windowResizeHandler = Window.addResizeHandler(new ResizeHandler() {
#Override
public void onResize(ResizeEvent event) {
checkIfScrollButtonsNecessary();
}
});
}
}
#Override
protected void onUnload() {
super.onUnload();
if (windowResizeHandler != null) {
windowResizeHandler.removeHandler();
windowResizeHandler = null;
}
}
private ClickHandler createScrollClickHandler(final int diff) {
return new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
Widget lastTab = getLastTab();
if (lastTab == null)
return;
int newLeft = parsePosition(tabBar.getElement().getStyle().getLeft()) + diff;
int rightOfLastTab = getRightOfWidget(lastTab);
// Prevent scrolling the last tab too far away form the right border,
// or the first tab further than the left border position
if (newLeft <= 0 && (getTabBarWidth() - newLeft < (rightOfLastTab + 20))) {
scrollTo(newLeft);
}
}
};
}
/** Create and attach the scroll button images with a click handler */
private void initScrollButtons() {
scrollLeftButton = new Image(leftArrowImage);
int leftImageWidth = scrollLeftButton.getWidth();
panel.insert(scrollLeftButton, 0);
panel.setWidgetLeftWidth(scrollLeftButton, 0, Unit.PX, leftImageWidth, Unit.PX);
panel.setWidgetTopHeight(scrollLeftButton, 0, Unit.PX, scrollLeftButton.getWidth(), Unit.PX);
scrollLeftButton.addClickHandler(createScrollClickHandler(+20));
scrollLeftButton.setVisible(false);
scrollRightButton = new Image(rightArrowImage);
panel.insert(scrollRightButton, 0);
panel.setWidgetLeftWidth(scrollRightButton, leftImageWidth + IMAGE_PADDING_PIXELS, Unit.PX, scrollRightButton.getWidth(), Unit.PX);
panel.setWidgetTopHeight(scrollRightButton, 0, Unit.PX, scrollRightButton.getHeight(), Unit.PX);
scrollRightButton.addClickHandler(createScrollClickHandler(-20));
scrollRightButton.setVisible(false);
}
private void checkIfScrollButtonsNecessary() {
// Defer size calculations until sizes are available, when calculating immediately after
// add(), all size methods return zero
Scheduler.get().scheduleDeferred( new Scheduler.ScheduledCommand() {
#Override
public void execute() {
boolean isScrolling = isScrollingNecessary();
// When the scroll buttons are being hidden, reset the scroll position to zero to
// make sure no tabs are still out of sight
if (scrollRightButton.isVisible() && !isScrolling) {
resetScrollPosition();
}
scrollRightButton.setVisible(isScrolling);
scrollLeftButton.setVisible(isScrolling);
}
}
);
}
private void resetScrollPosition() {
scrollTo(0);
}
private void scrollTo(int pos) {
tabBar.getElement().getStyle().setLeft(pos, Unit.PX);
}
private boolean isScrollingNecessary() {
Widget lastTab = getLastTab();
if (lastTab == null)
return false;
return getRightOfWidget(lastTab) > getTabBarWidth();
}
private int getRightOfWidget(Widget widget) {
return widget.getElement().getOffsetLeft() + widget.getElement().getOffsetWidth();
}
private int getTabBarWidth() {
return tabBar.getElement().getParentElement().getClientWidth();
}
private Widget getLastTab() {
if (tabBar.getWidgetCount() == 0)
return null;
return tabBar.getWidget(tabBar.getWidgetCount() - 1);
}
private static int parsePosition(String positionString) {
int position;
try {
for (int i = 0; i < positionString.length(); i++) {
char c = positionString.charAt(i);
if (c != '-' && !(c >= '0' && c <= '9')) {
positionString = positionString.substring(0, i);
}
}
position = Integer.parseInt(positionString);
} catch (NumberFormatException ex) {
position = 0;
}
return position;
}
}
Here is the code I tried to make the flextable's cell editable
The flex table is loaded with db values, when user clicks on the cell of flextable, it has to become editable and the user entered value has to be stored in db, after the user clicks submit button which is present at each row.
I'm using EditTextCell(), to make the cell editable but it not becoming editable when I test it. I have included all my codes below. Please let me know , if i'm missing anything.
private List<PendingChange<?>> pendingChanges = new ArrayList<PendingChange<?>>();
private List<AbstractEditableCell<?, ?>> editableCells = new ArrayList<AbstractEditableCell<?, ?>>();
CellTable cellTable= new CellTable<MessageEvent>();
EditTextCell editCell = new EditTextCell();
protected FlexTable flextable;
//flextable creation
private final void createWorkflows(List<MessageEvent> theWorkflowMessageEvents, boolean isSelectAll) {
int row = 1;
if (theWorkflowMessageEvents != null) {
for (final MessageEvent workflowMessageEvent : theWorkflowMessageEvents) {
flextable.getRowFormatter().setStyleName(row,ACTIVE_COLLECTION);
flextable.getCellFormatter().setHorizontalAlignment(row, 0, HasHorizontalAlignment.ALIGN_LEFT);
flextable.getCellFormatter().setWordWrap(row, 0, false);
flextable.setText(row, 0, workflowMessageEvent.getTransferReceived());
flextable.getCellFormatter().setHorizontalAlignment(row, 1, HasHorizontalAlignment.ALIGN_LEFT);
flextable.getCellFormatter().setWordWrap(row, 1, false);
flextable.setText(row, 1, workflowMessageEvent.getLoadReceived());
makeFlexTableEditable() ;
Button submitButton= new Button("Submit");
flextable.getCellFormatter().setHorizontalAlignment(row, 3, HasHorizontalAlignment.ALIGN_LEFT);
flextable.getCellFormatter().setWordWrap(row, 3, false);
flextable.setWidget(row, 3,submitButton );
submitWorklow(submitButton,row, workflowMessageEvent);
flextable.getRowFormatter().setVisible(row, true);
row++;
}
}
}
//adding flextable to main panel
protected void displayPendingWorkflows(final List<MessageEvent> theWorkflowMessageEvents) {
this.createPendingWorkflows(theWorkflowMessageEvents, false);
//some code
mainPanel.add(flextable);
mainPanel.add(cellTable);
}
//code for making flex table editable for TransferReceived column
private void makeFlexTableEditable() {
addColumn(new EditTextCell(), new GetValue() {
#Override
public String getValue(MessageEvent workflowMessageEvent) {
return workflowMessageEvent.getTransferReceived();
}
}, new FieldUpdater<MessageEvent, String>() {
public void update(int index, MessageEvent workflowMessageEvent, String value) {
try { pendingChanges.add(new TransferReceived(workflowMessageEvent, value));
}catch (Exception e) {
}
}
});
}
private <C> Column<MessageEvent, String> addColumn(EditTextCell cell,
final GetValue<String> getter,FieldUpdater<MessageEvent, String> fieldUpdater) {
Column<MessageEvent, String> transColumn = new Column<MessageEvent, String>(cell){
#Override
public String getValue(MessageEvent object) {
return getter.getValue(object);
}
};
transColumn.setFieldUpdater(fieldUpdater);
if (cell instanceof AbstractEditableCell<?, ?>) {
editableCells.add((AbstractEditableCell<?, ?>) cell);
}
cellTable.addColumn(transColumn);
return transColumn;
}
/**
* A pending change to a {#link MessageEvent}. Changes aren't committed
* immediately to illustrate that cells can remember their pending changes.
*
* #param <T> the data type being changed
*/
private abstract static class PendingChange<T> {
private final MessageEvent message;
private final T value;
public PendingChange(MessageEvent message, T value) {
this.message = message;
this.value = value;
}
/**
* Commit the change to the contact.
*/
public void commit() {
doCommit(message, value);
}
/**
* Update the appropriate field in the .
*
* #param message to update
* #param value the new value
*/
protected abstract void doCommit(MessageEvent message, T value);
}
/**
* Updates the Transfered Received.
*/
private static class TransferReceived extends PendingChange<String> {
public TransferReceived(MessageEvent message, String value) {
super(message, value);
}
#Override
protected void doCommit(MessageEvent message, String value) {
message.setTransferReceived(value);
}
}
/**
* Get a cell value from a record.
*
* #param <C> the cell type
*/
private static interface GetValue<C> {
C getValue(MessageEvent message);
}
I did something like this in my app. Sorry if the syntax is a bit off but the main idea is to use a clickevent and then get this events position and exchange the widget in that position.
final FlexTable flexTable = new FlexTable();
flexTable.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
Cell cell = flexTable.getCellForClickEvent(event);
final int row = cell.getRow();
final int column = cell.getIndex();
final TextBox textBox = new TextBox();
// Get the text from the cell in some way. Maybe use flextTable.getHTML(row, column) or what ever you prefer
// textBox.setText("Something other than this");
textBox.addKeyDownHandler(new KeyDownHandler() {
public void onKeyDownEvent(KeyDownEvent event) {
int code = event.getNativeKeyCode();
if (KeyCodes.KEY_ENTER == code) {
flexTable.setWidget(row, column, new Label(textBox.getText()));
}
}
});
flexTable.setWidget(row, column, textBox);
// You may also need something like this
textBox.setFocus(true);
}
});