From 1be58bdddbedcd6282583d7851a2dc132ce8880a Mon Sep 17 00:00:00 2001 From: David Aguiar Date: Mon, 2 May 2016 14:23:39 +0200 Subject: [PATCH] Add "select/deselect all" checkbox (#89) * Added checkbox at the beginning of EntryHeader * Added 'de-select all' checkbox behaviour * Added a new View in test-app to test new behaviour --- .../butterknifezelezny/form/Entry.java | 14 ++++++++ .../butterknifezelezny/form/EntryHeader.java | 34 +++++++++++++++++- .../butterknifezelezny/form/EntryList.java | 36 ++++++++++++++++++- .../iface/OnCheckBoxStateChangedListener.java | 5 +++ .../app/src/main/res/layout/activity_main.xml | 8 ++++- 5 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 src/com/avast/android/butterknifezelezny/iface/OnCheckBoxStateChangedListener.java diff --git a/src/com/avast/android/butterknifezelezny/form/Entry.java b/src/com/avast/android/butterknifezelezny/form/Entry.java index 2aedd74..69c57dc 100644 --- a/src/com/avast/android/butterknifezelezny/form/Entry.java +++ b/src/com/avast/android/butterknifezelezny/form/Entry.java @@ -1,6 +1,7 @@ package com.avast.android.butterknifezelezny.form; +import com.avast.android.butterknifezelezny.iface.OnCheckBoxStateChangedListener; import com.avast.android.butterknifezelezny.model.Element; import javax.swing.*; @@ -16,6 +17,7 @@ public class Entry extends JPanel { protected EntryList mParent; protected Element mElement; protected ArrayList mGeneratedIDs; + protected OnCheckBoxStateChangedListener mListener; // ui protected JCheckBox mCheck; protected JLabel mType; @@ -25,6 +27,14 @@ public class Entry extends JPanel { protected Color mNameDefaultColor; protected Color mNameErrorColor = new Color(0x880000); + public JCheckBox getCheck() { + return mCheck; + } + + public void setListener(final OnCheckBoxStateChangedListener onStateChangedListener) { + this.mListener = onStateChangedListener; + } + public Entry(EntryList parent, Element element, ArrayList ids) { mElement = element; mParent = parent; @@ -103,6 +113,10 @@ private void checkState() { mID.setEnabled(false); mName.setEnabled(false); } + + if (mListener != null) { + mListener.changeState(mCheck.isSelected()); + } } // classes diff --git a/src/com/avast/android/butterknifezelezny/form/EntryHeader.java b/src/com/avast/android/butterknifezelezny/form/EntryHeader.java index 2457820..cdee409 100644 --- a/src/com/avast/android/butterknifezelezny/form/EntryHeader.java +++ b/src/com/avast/android/butterknifezelezny/form/EntryHeader.java @@ -1,16 +1,31 @@ package com.avast.android.butterknifezelezny.form; +import com.avast.android.butterknifezelezny.iface.OnCheckBoxStateChangedListener; + import javax.swing.*; import java.awt.*; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; public class EntryHeader extends JPanel { + protected JCheckBox mAllCheck; protected JLabel mType; protected JLabel mID; protected JLabel mEvent; protected JLabel mName; + protected OnCheckBoxStateChangedListener mAllListener; + + public void setAllListener(final OnCheckBoxStateChangedListener onStateChangedListener) { + this.mAllListener = onStateChangedListener; + } public EntryHeader() { + mAllCheck = new JCheckBox(); + mAllCheck.setPreferredSize(new Dimension(40, 26)); + mAllCheck.setSelected(false); + mAllCheck.addItemListener(new AllCheckListener()); + mType = new JLabel("Element"); mType.setPreferredSize(new Dimension(100, 26)); mType.setFont(new Font(mType.getFont().getFontName(), Font.BOLD, mType.getFont().getSize())); @@ -28,7 +43,9 @@ public EntryHeader() { mName.setFont(new Font(mName.getFont().getFontName(), Font.BOLD, mName.getFont().getSize())); setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS)); - add(Box.createRigidArea(new Dimension(52, 0))); + add(Box.createRigidArea(new Dimension(1, 0))); + add(mAllCheck); + add(Box.createRigidArea(new Dimension(11, 0))); add(mType); add(Box.createRigidArea(new Dimension(12, 0))); add(mID); @@ -38,4 +55,19 @@ public EntryHeader() { add(mName); add(Box.createHorizontalGlue()); } + + public JCheckBox getAllCheck() { + return mAllCheck; + } + + // classes + + private class AllCheckListener implements ItemListener { + @Override + public void itemStateChanged(ItemEvent itemEvent) { + if (mAllListener != null) { + mAllListener.changeState(itemEvent.getStateChange() == ItemEvent.SELECTED); + } + } + } } diff --git a/src/com/avast/android/butterknifezelezny/form/EntryList.java b/src/com/avast/android/butterknifezelezny/form/EntryList.java index ad1360a..064d135 100644 --- a/src/com/avast/android/butterknifezelezny/form/EntryList.java +++ b/src/com/avast/android/butterknifezelezny/form/EntryList.java @@ -2,6 +2,7 @@ import com.avast.android.butterknifezelezny.iface.ICancelListener; import com.avast.android.butterknifezelezny.iface.IConfirmListener; +import com.avast.android.butterknifezelezny.iface.OnCheckBoxStateChangedListener; import com.avast.android.butterknifezelezny.model.Element; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; @@ -32,6 +33,32 @@ public class EntryList extends JPanel { protected JLabel mHolderLabel; protected JButton mConfirm; protected JButton mCancel; + protected EntryHeader mEntryHeader; + + private OnCheckBoxStateChangedListener allCheckListener = new OnCheckBoxStateChangedListener() { + @Override + public void changeState(boolean checked) { + for (final Entry entry : mEntries) { + entry.setListener(null); + entry.getCheck().setSelected(checked); + entry.setListener(singleCheckListener); + } + } + }; + + private OnCheckBoxStateChangedListener singleCheckListener = new OnCheckBoxStateChangedListener() { + @Override + public void changeState(boolean checked) { + boolean result = true; + for (Entry entry : mEntries) { + result &= entry.getCheck().isSelected(); + } + + mEntryHeader.setAllListener(null); + mEntryHeader.getAllCheck().setSelected(result); + mEntryHeader.setAllListener(allCheckListener); + } + }; public EntryList(Project project, Editor editor, ArrayList elements, ArrayList ids, boolean createHolder, IConfirmListener confirmListener, ICancelListener cancelListener) { mProject = project; @@ -57,7 +84,8 @@ protected void addInjections() { JPanel contentPanel = new JPanel(); contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.PAGE_AXIS)); contentPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); - contentPanel.add(new EntryHeader()); + mEntryHeader = new EntryHeader(); + contentPanel.add(mEntryHeader); contentPanel.add(Box.createRigidArea(new Dimension(0, 5))); JPanel injectionsPanel = new JPanel(); @@ -65,8 +93,10 @@ protected void addInjections() { injectionsPanel.add(Box.createRigidArea(new Dimension(0, 5))); int cnt = 0; + boolean selectAllCheck = true; for (Element element : mElements) { Entry entry = new Entry(this, element, mGeneratedIDs); + entry.setListener(singleCheckListener); if (cnt > 0) { injectionsPanel.add(Box.createRigidArea(new Dimension(0, 5))); @@ -75,7 +105,11 @@ protected void addInjections() { cnt++; mEntries.add(entry); + + selectAllCheck &= entry.getCheck().isSelected(); } + mEntryHeader.getAllCheck().setSelected(selectAllCheck); + mEntryHeader.setAllListener(allCheckListener); injectionsPanel.add(Box.createVerticalGlue()); injectionsPanel.add(Box.createRigidArea(new Dimension(0, 5))); diff --git a/src/com/avast/android/butterknifezelezny/iface/OnCheckBoxStateChangedListener.java b/src/com/avast/android/butterknifezelezny/iface/OnCheckBoxStateChangedListener.java new file mode 100644 index 0000000..09b5bcd --- /dev/null +++ b/src/com/avast/android/butterknifezelezny/iface/OnCheckBoxStateChangedListener.java @@ -0,0 +1,5 @@ +package com.avast.android.butterknifezelezny.iface; + +public interface OnCheckBoxStateChangedListener { + void changeState(boolean checked); +} diff --git a/test-app/app/src/main/res/layout/activity_main.xml b/test-app/app/src/main/res/layout/activity_main.xml index ead92a8..7be50a1 100644 --- a/test-app/app/src/main/res/layout/activity_main.xml +++ b/test-app/app/src/main/res/layout/activity_main.xml @@ -4,4 +4,10 @@ android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" - tools:ignore="MergeRootFrame"/> + tools:ignore="MergeRootFrame"> + + + +