diff --git a/.idea/misc.xml b/.idea/misc.xml index fbb6828..5d19981 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -37,7 +37,7 @@ - + diff --git a/app/build.gradle b/app/build.gradle index f7c9d6b..b8a8cf2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,7 +10,7 @@ android { } */ defaultConfig { - applicationId "hikapro.com.backpack" + applicationId "com.hikapro.backpack" minSdkVersion 17 targetSdkVersion 23 versionCode 1 @@ -28,12 +28,12 @@ dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' + compile 'com.google.code.gson:gson:2.6.2' compile 'com.squareup.retrofit2:retrofit:2.0.1' compile 'com.squareup.retrofit2:converter-gson:2.0.1' compile 'com.squareup.okhttp3:okhttp:3.2.0' compile 'com.squareup.okhttp:logging-interceptor:2.7.0' - compile 'com.android.support:support-v4:23.3.0' compile 'com.android.support:appcompat-v7:23.3.0' compile 'com.android.support:design:23.3.0' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0a8ca4c..df33a52 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,6 +2,7 @@ + @@ -28,6 +38,10 @@ public class DetailModel implements Model.Detail { return item; } + @Override + public Bitmap getPicture() { + return pic; + } // detail <-- // events --> @@ -52,7 +66,14 @@ public class DetailModel implements Model.Detail { // process --> @Override public void executeQuery() { + notifyDataSetChanged(); + Message command; + command = Message.obtain(); + command.what = Command.ITEM_GET_IMAGE; + command.arg1 = item.getId(); + dao.executeCommand(command); + } // process <-- @@ -61,7 +82,6 @@ public class DetailModel implements Model.Detail { public void setPresenter(Presenter.ItemDetail presenter) { this.presenter = presenter; this.item = presenter.getCurrentItem(); - } @Override @@ -72,5 +92,14 @@ public class DetailModel implements Model.Detail { @Override public void onEvent(Message event) { + switch (event.what) { + case Event.ITEM_IMAGE_LOAD_ERROR : + break; + case Event.ITEM_IMAGE_LOAD_COMPLETED : + pic = (Bitmap) event.obj; + notifyDataSetChanged(); + break; + } + } } diff --git a/app/src/main/java/hikapro/com/backpack/model/ItemModel.java b/app/src/main/java/hikapro/com/backpack/model/ItemModel.java index 459617b..3d94c9e 100644 --- a/app/src/main/java/hikapro/com/backpack/model/ItemModel.java +++ b/app/src/main/java/hikapro/com/backpack/model/ItemModel.java @@ -21,19 +21,21 @@ import hikapro.com.backpack.presenter.Presenter; */ public class ItemModel implements Model.Item { - private Presenter.ItemList presenter; + protected Presenter.ItemList presenter; private List rawCategories; private List sortedCategories; private List rawItems; - private DAO dao; - private int currentSet; - private Hashtable categoriesCache; + protected DAO dao; + protected int currentSet; + protected int currentSetActiveItemsQty; + protected int packedQty; + protected Hashtable categoriesCache; private List itemsCache; private List itemsDiscardCache; private Hashtable> items; - private Hashtable> cache; + protected Hashtable> cache; public ItemModel() { this.rawCategories = new ArrayList<>(); @@ -42,6 +44,8 @@ public class ItemModel implements Model.Item { this.categoriesCache = new Hashtable<>(20, 0.9f); + this.packedQty = -1; + this.itemsCache = new ArrayList<>(); this.itemsDiscardCache = new ArrayList<>(); this.cache = new Hashtable<>(12, 0.9f); @@ -59,7 +63,6 @@ public class ItemModel implements Model.Item { return ret; } - // categories <-- // items --> @@ -70,6 +73,7 @@ public class ItemModel implements Model.Item { iList.add(item); Collections.sort(iList); cache.put(currentSet, iList); + ++currentSetActiveItemsQty; // TODO write to database return 0; } @@ -78,6 +82,7 @@ public class ItemModel implements Model.Item { if (isPendingRemoval(item)) itemsDiscardCache.remove(item); cache.get(currentSet).remove(item); + --currentSetActiveItemsQty; //TODO write to ds return false; @@ -168,6 +173,15 @@ public class ItemModel implements Model.Item { return is ? cache.get(currentSet).size() : 0; } + @Override + public int getActiveItemsCount() { + return currentSetActiveItemsQty; + } + + @Override + public int getPackedQty() { + return packedQty; + } // items <-- // events --> @@ -192,6 +206,29 @@ public class ItemModel implements Model.Item { // process --> + + @Override + public void packItem(int itemId) { + Item item = findItem(itemId); + if (item != null) + cache.get(currentSet).remove(item); + Message command = Message.obtain(); + command.what = Command.ITEM_PACK; + command.arg1 = currentSet; + command.arg2 = itemId; + dao.executeCommand(command); + } + + @Override + public void unpackItem(int itemId) { + // nothing + } + + @Override + public void unpackSet(int setId) { + // nothing + } + @Override public void executeQuery() { Message command; @@ -208,14 +245,20 @@ public class ItemModel implements Model.Item { command.what = Command.SET_GET_ITEMS; command.arg1 = presenter.getCurrentSet().getId(); dao.executeCommand(command); - } } @Override public void onEvent(Message event) { switch (event.what) { - case Event.SET_ITEMS_LOAD_ERROR : + case Event.SET_ITEMS_LOAD_ERROR : // TODO check + if (presenter != null) { + if (packedQty == -1) + packedQty = presenter.getCurrentSet().getPackedQty(); + presenter.notifyItemPackStatusChanged(); + } + break; + case Event.SET_UNPACK_ERROR : break; case Event.ITEM_FROM_SET_ERROR : break; @@ -233,6 +276,17 @@ public class ItemModel implements Model.Item { List res = (List) event.obj; cache.put(event.arg1, res); notifyDataSetChanged(); + if (presenter != null) { + if (packedQty == -1) + packedQty = presenter.getCurrentSet().getPackedQty(); + presenter.notifyItemPackStatusChanged(); + } + break; + case Event.SET_UNPACK_COMPLETED : + packedQty = 0; + if (presenter != null) { + presenter.notifyItemPackStatusChanged(); + } break; case Event.ITEM_CATEGORY_LOAD_COMPLETED : categoriesCache = (Hashtable)event.obj; @@ -242,8 +296,17 @@ public class ItemModel implements Model.Item { case Event.ITEM_DELETED : break; case Event.ITEM_PACKED : + //TODO something + ++packedQty; + if (presenter != null) { + presenter.notifyItemPackStatusChanged(); + } break; case Event.ITEM_UNPACKED : + --packedQty; + if (presenter != null) { + presenter.notifyItemPackStatusChanged(); + } break; case Event.ITEM_INSERTED : break; @@ -257,8 +320,9 @@ public class ItemModel implements Model.Item { @Override public void setPresenter(Presenter.ItemList presenter) { - this.presenter = presenter; - this.currentSet = presenter.getCurrentSet().getId(); + this.presenter = presenter; + this.currentSet = presenter.getCurrentSet().getId(); + this.currentSetActiveItemsQty = presenter.getCurrentSet().getActiveQty(); } @Override @@ -266,45 +330,6 @@ public class ItemModel implements Model.Item { return presenter; } - private void initData() { - List ids = presenter.getCurrentSet().getItems(); - List sortedItems = new ArrayList<>(ids.size()); - Category category; - - for (Item item : rawItems) { - if (ids.contains(item.getId())) { - sortedItems.add(item); - } - } - Collections.sort(sortedItems); - items = new Hashtable<>(sortedItems.size()); - - for (Item item : sortedItems) { - category = findCategory(item.getCategory()); - if (category != null) { - if (items.containsKey(category)) { - items.get(category).add(item); - } else { - List innerList = new ArrayList<>(20); - innerList.add(item); - items.put(category, innerList); - } - } - } - Category[] array = items.keySet().toArray(new Category[items.size()]); - sortedCategories = Arrays.asList(array); - notifyDataSetChanged(); - } - private Category findSortedCategory(int categoryId) { - Category category = null; - for (Category c : sortedCategories) { - if (c.getId() == categoryId) { - category = c; - break; - } - } - return category; - } private Category findCategory(int categoryId) { Category category = null; diff --git a/app/src/main/java/hikapro/com/backpack/model/Model.java b/app/src/main/java/hikapro/com/backpack/model/Model.java index 157a71b..0cca863 100644 --- a/app/src/main/java/hikapro/com/backpack/model/Model.java +++ b/app/src/main/java/hikapro/com/backpack/model/Model.java @@ -1,5 +1,6 @@ package hikapro.com.backpack.model; +import android.graphics.Bitmap; import android.os.Message; import java.util.List; @@ -43,6 +44,8 @@ public interface Model { void pendingRemove(hikapro.com.backpack.model.entities.Item item); void pendingRemoveCancel(hikapro.com.backpack.model.entities.Item item); int getItemsCount(); + int getActiveItemsCount(); + int getPackedQty(); hikapro.com.backpack.model.entities.Item findItem(int id); hikapro.com.backpack.model.entities.Item getItemByPosition(int position); @@ -50,13 +53,20 @@ public interface Model { hikapro.com.backpack.model.entities.Category getCategoryByPosition(int position); void setPresenter(Presenter.ItemList presenter); Presenter.ItemList getPresenter(); + + void packItem(int itemId); + void unpackItem(int itemId); + void unpackSet(int setId); } + interface Detail extends Base { int getCount(); hikapro.com.backpack.model.entities.Item findItem(int id); + Bitmap getPicture(); void setPresenter(Presenter.ItemDetail presenter); Presenter.ItemDetail getPresenter(); - } + + } diff --git a/app/src/main/java/hikapro/com/backpack/model/PackedModel.java b/app/src/main/java/hikapro/com/backpack/model/PackedModel.java new file mode 100644 index 0000000..6d18301 --- /dev/null +++ b/app/src/main/java/hikapro/com/backpack/model/PackedModel.java @@ -0,0 +1,121 @@ +package hikapro.com.backpack.model; + +import android.os.Message; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Hashtable; +import java.util.List; + +import hikapro.com.backpack.model.dao.Command; +import hikapro.com.backpack.model.dao.DAO; +import hikapro.com.backpack.model.dao.Event; +import hikapro.com.backpack.model.entities.Category; +import hikapro.com.backpack.model.entities.Item; +import hikapro.com.backpack.presenter.Presenter; + +/** + * Created by tariel on 12/05/16. + */ +public class PackedModel extends ItemModel { + + public PackedModel() { + super(); + } + + @Override + public void executeQuery() { + Message command; + + if (cache.contains(currentSet)) { + notifyDataSetChanged(); + } else { + if (categoriesCache.isEmpty()) { + command = Message.obtain(); + command.what = Command.ITEM_GET_CATEGORIES; + dao.executeCommand(command); + } + command = Message.obtain(); + command.what = Command.SET_GET_PACKED_ITEMS; + command.arg1 = presenter.getCurrentSet().getId(); + dao.executeCommand(command); + } + } + + @Override + public void onEvent(Message event) { + + switch (event.what) { + + case Event.SET_PACKED_LOAD_ERROR : + break; + case Event.SET_UNPACK_ERROR : + break; + case Event.ITEM_CATEGORY_LOAD_ERROR : + break; + case Event.ITEM_PACK_ERROR : + break; + case Event.ITEM_UNPACK_ERROR : + break; + case Event.SET_PACKED_LOAD_COMPLETED : + List res = (List) event.obj; + cache.put(event.arg1, res); + notifyDataSetChanged(); + packedQty = res.size(); + if (presenter != null) { + presenter.notifyItemPackStatusChanged(); + } + break; + case Event.SET_UNPACK_COMPLETED : + packedQty = 0; + cache.get(event.arg2).clear(); + if (presenter != null) { + presenter.notifyItemPackStatusChanged(); + } + break; + case Event.ITEM_CATEGORY_LOAD_COMPLETED : + categoriesCache = (Hashtable)event.obj; + break; + case Event.ITEM_PACKED : + //TODO something + ++packedQty; + if (presenter != null) { + presenter.notifyItemPackStatusChanged(); + } + break; + case Event.ITEM_UNPACKED : + --packedQty; + if (presenter != null) { + presenter.notifyItemPackStatusChanged(); + } + break; + } + } + + @Override + public void unpackItem(int itemId) { + Message command; + command = Message.obtain(); + command.what = Command.ITEM_UNPACK; + command.arg1 = currentSet; + command.arg2 = itemId; + dao.executeCommand(command); + Item item = findItem(itemId); + if (item != null) + cache.get(currentSet).remove(item); + } + + @Override + public void packItem(int itemId) { + // nothing + } + + @Override + public void unpackSet(int setId) { + Message command; + command = Message.obtain(); + command.what = Command.SET_UNPACK_ITEMS; + command.arg1 = setId; + dao.executeCommand(command); + } +} diff --git a/app/src/main/java/hikapro/com/backpack/model/dao/Command.java b/app/src/main/java/hikapro/com/backpack/model/dao/Command.java index 5542a54..204c349 100644 --- a/app/src/main/java/hikapro/com/backpack/model/dao/Command.java +++ b/app/src/main/java/hikapro/com/backpack/model/dao/Command.java @@ -13,12 +13,15 @@ public interface Command { int SET_GET_ALL = 0x64; int SET_REORDER = 0x65; int SET_GET_ITEMS = 0x66; + int SET_GET_PACKED_ITEMS = 0x67; + int SET_UNPACK_ITEMS = 0x68; int ITEM_DELETE_FROM_SET = 0x78; int ITEM_INSERT = 0x79; int ITEM_PACK = 0x7A; int ITEM_UNPACK = 0x7B; int ITEM_GET_CATEGORIES = 0x7C; + int ITEM_GET_IMAGE = 0x7D; int MY_LIST_POST = 0x8C; int MY_LIST_ITEM_ADD = 0x8D; diff --git a/app/src/main/java/hikapro/com/backpack/model/dao/DAO.java b/app/src/main/java/hikapro/com/backpack/model/dao/DAO.java index 44a87e9..6c7c003 100644 --- a/app/src/main/java/hikapro/com/backpack/model/dao/DAO.java +++ b/app/src/main/java/hikapro/com/backpack/model/dao/DAO.java @@ -5,6 +5,8 @@ import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -108,6 +110,7 @@ public class DAO { SetTask setTask; ItemTask itemTask; + ImageProviderTask imageProviderTask; if (command != null) { switch (command.what) { @@ -132,6 +135,19 @@ public class DAO { threadPool.execute(setTask); break; + case Command.SET_GET_PACKED_ITEMS : + setTask = new SetTask(Command.SET_GET_PACKED_ITEMS, + Process.THREAD_PRIORITY_MORE_FAVORABLE); + setTask.setId = command.arg1; + threadPool.execute(setTask); + break; + + case Command.SET_UNPACK_ITEMS : + setTask = new SetTask(Command.SET_UNPACK_ITEMS, + Process.THREAD_PRIORITY_DEFAULT); + setTask.setId = command.arg1; + threadPool.execute(setTask); + case Command.ITEM_GET_CATEGORIES : itemTask = new ItemTask(Command.ITEM_GET_CATEGORIES, Process.THREAD_PRIORITY_MORE_FAVORABLE); @@ -170,6 +186,16 @@ public class DAO { threadPool.execute(itemTask); break; + case Command.ITEM_GET_IMAGE : + Item item = findItem(command.arg1); + if (item != null) { + imageProviderTask = new ImageProviderTask(Command.ITEM_GET_IMAGE, + Process.THREAD_PRIORITY_DEFAULT); + imageProviderTask.item = item; + threadPool.execute(imageProviderTask); + } + break; + case Command.MY_LIST_ITEM_ADD : break; @@ -320,20 +346,56 @@ public class DAO { db.close(); return ret; } - private List readItems(int setId) { + + private Item findItem(int id) { + Item ret = null; + Cursor cursor = null; + SQLiteDatabase db = null; + try { + db = getReadDB(); + String query = String.format("SELECT * FROM %s a WHERE a.%s = %d LIMIT 1", + Db.ItemsTable.TABLE_NAME, Db.ItemsTable.COLUMN_ID, id); + cursor = db.rawQuery(query, null); + if (cursor.moveToNext()) { + ret = Db.ItemsTable.parseCursor(cursor); + } + } catch (Exception e) { + //TODO write to log here + } finally { + if (cursor != null) + cursor.close(); + if (db != null) + db.close(); + } + return ret; + } + + private List readItems(int setId, boolean packed) { List ret = new ArrayList<>(256); Cursor cursor = null; SQLiteDatabase db = null; Item item; String query = String.format( - "SELECT * FROM %s a INNER JOIN %s b ON a.%s = b.%s WHERE b.%s = ? AND b.%s <> 1 AND b.%s <> 1", + "SELECT a.%s, a.%s, a.%s, a.%s, a.%s, a.%s, a.%s, a.%s, a.%s FROM %s a INNER JOIN %s b ON a.%s = b.%s WHERE b.%s = ? AND b.%s <> 1 AND b.%s %s 1", + + Db.ItemsTable.COLUMN_ID, + Db.ItemsTable.COLUMN_NAME, + Db.ItemsTable.COLUMN_CATEGORY, + Db.ItemsTable.COLUMN_DESCRIPTION, + Db.ItemsTable.COLUMN_BUY_URLS, + Db.ItemsTable.COLUMN_PHOTO_URL, + Db.ItemsTable.COLUMN_PHOTO_THUMB_URL, + Db.ItemsTable.COLUMN_PHOTO_LOCAL, + Db.ItemsTable.COLUMN_PHOTO_THUMB_LOCAL, + Db.ItemsTable.TABLE_NAME, Db.SetItemsTable.TABLE_NAME, Db.ItemsTable.COLUMN_ID, Db.SetItemsTable.COLUMN_ITEM, Db.SetItemsTable.COLUMN_SET, Db.SetItemsTable.COLUMN_DELETED, - Db.SetItemsTable.COLUMN_PACKED); + Db.SetItemsTable.COLUMN_PACKED, + packed ? "=" : "<>"); try { db = getReadDB(); cursor = db.rawQuery(query, new String[]{String.valueOf(setId)}); @@ -382,6 +444,20 @@ public class DAO { } return ret; } + + private Set readSet(SQLiteDatabase db, int setId) { + Set ret = null; + Cursor cursor; + String query = String.format("SELECT * FROM %s a WHERE a.%s = %d LIMIT 1", + Db.SetsTable.TABLE_NAME, Db.SetsTable.COLUMN_ID, setId); + cursor = db.rawQuery(query, null); + if (cursor.moveToNext()) + ret = Db.SetsTable.parseCursor(cursor); + if (cursor != null) + cursor.close(); + return ret; + } + private List readSets() { List ret = new ArrayList<>(12); Cursor cursor = null; @@ -389,19 +465,8 @@ public class DAO { Set set; try { db = getReadDB(); - cursor = db.query(Db.SetsTable.TABLE_NAME, - new String[]{Db.SetsTable.COLUMN_ID, - Db.SetsTable.COLUMN_ITEMS, - Db.SetsTable.COLUMN_LINE_NUMBER, - Db.SetsTable.COLUMN_NAME, - Db.SetsTable.COLUMN_PHOTO_LOCAL, - Db.SetsTable.COLUMN_PHOTO_THUMB_LOCAL, - Db.SetsTable.COLUMN_PHOTO_THUMB_URL, - Db.SetsTable.COLUMN_PHOTO_THUMBNAIL_LOCAL, - Db.SetsTable.COLUMN_PHOTO_THUMBNAIL_URL, - Db.SetsTable.COLUMN_PHOTO_URL}, - null,null,null,null, - Db.SetsTable.COLUMN_LINE_NUMBER); + String query = String.format("SELECT * FROM %s", Db.SetsTable.TABLE_NAME); + cursor = db.rawQuery(query, null); while (cursor.moveToNext()) { set = Db.SetsTable.parseCursor(cursor); ret.add(set); @@ -421,6 +486,32 @@ public class DAO { return ret; } // updates + private int updateItemLocalPic(int id, String path) { + int ret = 0; + SQLiteDatabase db = null; + ContentValues values; + try { + db = getWriteDB(); + db.beginTransaction(); + values = new ContentValues(); + values.put(Db.ItemsTable.COLUMN_PHOTO_LOCAL, path); + ret = db.update(Db.ItemsTable.TABLE_NAME, values, "_id = ?", + new String[]{String.valueOf(id)}); + db.setTransactionSuccessful(); + } catch (SQLiteException e) { + //TODO write to log here + + } catch (Exception e) { + //TODO write to log here + } finally { + if (db != null) { + db.endTransaction(); + db.close(); + } + } + return ret; + } + private int updateSetsOrder(List reorderedSet) { int ret = 0; SQLiteDatabase db = null; @@ -475,10 +566,59 @@ public class DAO { } return ret; } + + private int updateSetItemsPacked(int setId, boolean pack) { + int ret = 0; + SQLiteDatabase db = null; + ContentValues values; + Set set; + try { + db = getWriteDB(); + db.beginTransaction(); + + /* + String query = String.format("UPDATE %s SET %s = %d where %s = %d", + Db.SetItemsTable.TABLE_NAME, + Db.SetItemsTable.COLUMN_PACKED, + pack, + Db.SetItemsTable.COLUMN_SET, + setId); + Cursor cursor = db.rawQuery(query, null);*/ + + values = new ContentValues(); + values.put(Db.SetItemsTable.COLUMN_PACKED, pack); + ret = db.update(Db.SetItemsTable.TABLE_NAME, values, String.format("%s = ?", + Db.SetItemsTable.COLUMN_SET), + new String[]{String.valueOf(setId)}); + + set = readSet(db, setId); + if (set != null) { + values = new ContentValues(); + values.put(Db.SetsTable.COLUMN_PACKED_QTY, pack ? set.getActiveQty() : 0); + ret += db.update(Db.SetsTable.TABLE_NAME, values, String.format("%s = ?", + Db.SetsTable.COLUMN_ID), + new String[]{String.valueOf(setId)}); + } + db.setTransactionSuccessful(); + } catch (SQLiteException e) { + //TODO write to log here + + } catch (Exception e) { + //TODO write to log here + } finally { + if (db != null) { + db.endTransaction(); + db.close(); + } + } + return ret; + } + private int updateSetItemPacked(int setId, int itemId, boolean pack) { int ret = 0; SQLiteDatabase db = null; ContentValues values; + Set set; try { db = getWriteDB(); db.beginTransaction(); @@ -489,13 +629,13 @@ public class DAO { Db.SetItemsTable.COLUMN_SET, Db.SetItemsTable.COLUMN_ITEM ), new String[]{String.valueOf(setId), String.valueOf(itemId)}); - if (pack) { - values = Db.SetItemsTable.toContentValues(MY_LIST_ID, itemId); - db.insert(Db.SetItemsTable.TABLE_NAME, null, values); - } else { - db.delete(Db.SetItemsTable.TABLE_NAME, String.format("%s = ? AND %s = ?", - Db.SetItemsTable.COLUMN_SET, Db.SetItemsTable.COLUMN_ITEM ), - new String[]{String.valueOf(MY_LIST_ID), String.valueOf(itemId) }); + set = readSet(db, setId); + if (set != null) { + values = new ContentValues(); + values.put(Db.SetsTable.COLUMN_PACKED_QTY, pack ? set.getPackedQty() + 1 : set.getPackedQty() - 1); + ret += db.update(Db.SetsTable.TABLE_NAME, values, String.format("%s = ?", + Db.SetsTable.COLUMN_ID), + new String[]{String.valueOf(setId)}); } db.setTransactionSuccessful(); } catch (SQLiteException e) { @@ -616,6 +756,7 @@ public class DAO { int priority; int setId; List setsToUpdate; + List items; public SetTask(int command, int priority) { this.currentCommand = command; @@ -641,7 +782,7 @@ public class DAO { break; case Command.SET_GET_ITEMS : - List items = readItems(setId); + items = readItems(setId, false); if (items.isEmpty()) message.what = Event.SET_ITEMS_LOAD_ERROR; else { @@ -659,6 +800,27 @@ public class DAO { else message.what = Event.SET_REORDER_ERROR; break; + + case Command.SET_GET_PACKED_ITEMS : + items = readItems(setId, true); + if (items.isEmpty()) + message.what = Event.SET_PACKED_LOAD_ERROR; + else { + Collections.sort(items); + message.what = Event.SET_PACKED_LOAD_COMPLETED; + message.obj = items; + message.arg1 = setId; + } + break; + + case Command.SET_UNPACK_ITEMS : + message.arg1 = updateSetItemsPacked(setId, false); + message.arg2 = setId; + if (message.arg1 > 0) + message.what = Event.SET_UNPACK_COMPLETED; + else + message.what = Event.SET_UNPACK_ERROR; + break; } handler.sendMessage(message); } @@ -738,7 +900,67 @@ public class DAO { } } } + // IMAGE PROVIDER CLASS + private class ImageProviderTask implements Runnable { + int currentCommand; + int priority; + Item item; + + + public ImageProviderTask(int command, int priority) { + this.currentCommand = command; + this.priority = priority; + } + + @Override + public void run() { + android.os.Process.setThreadPriority(priority); + Message message = Message.obtain(); + switch (currentCommand) { + + case Command.ITEM_GET_IMAGE : + try { + Bitmap bitmap = loadItemImage(item); + if (bitmap != null) { + message.what = Event.ITEM_IMAGE_LOAD_COMPLETED; + message.obj = bitmap; + } + else + message.what = Event.ITEM_IMAGE_LOAD_ERROR; + } catch (Exception e) { + message.what = Event.ITEM_IMAGE_LOAD_ERROR; + } + break; + } + handler.sendMessage(message); + } + } //endregion + private Bitmap loadItemImage(Item item){ + ImageDownloadHelper downloadHelper = new ImageDownloadHelper(); + Bitmap bitmap = null; + String filename = null; + + if (item != null) { + bitmap = BitmapFactory.decodeFile(item.getPhotoLocal()); + // cannot retrieve, download and save then + if (bitmap == null) { // return it + bitmap = downloadHelper.loadImage(item.getPhotoUrl()); + if (bitmap != null) { + if (downloadHelper.isExternalStorageWritable()) { + filename = downloadHelper.saveImageExternal( + downloadHelper.generateFileName(item.getPhotoUrl()), bitmap); + } else { + filename = downloadHelper.saveImageInternal( + downloadHelper.generateFileName(item.getPhotoUrl()), bitmap); + } + updateItemLocalPic(item.getId(), filename); + } + } + } + return bitmap; + } + } diff --git a/app/src/main/java/hikapro/com/backpack/model/dao/Db.java b/app/src/main/java/hikapro/com/backpack/model/dao/Db.java index 26c643b..702c3c8 100644 --- a/app/src/main/java/hikapro/com/backpack/model/dao/Db.java +++ b/app/src/main/java/hikapro/com/backpack/model/dao/Db.java @@ -96,8 +96,9 @@ public class Db { values.put(COLUMN_PHOTO_URL, item.getPhotoUrl()); if (item.getPhotoThumbUrl() != null) values.put(COLUMN_PHOTO_THUMB_URL, item.getPhotoThumbUrl()); + if (item.getPhotoLocal() != null) + values.put(COLUMN_PHOTO_LOCAL, item.getPhotoLocal()); /* - values.put(COLUMN_PHOTO_LOCAL, ); values.put(COLUMN_PHOTO_THUMB_LOCAL, item.getName()); */ return values; @@ -120,6 +121,7 @@ public class Db { } item.setPhotoUrl(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_PHOTO_URL))); item.setPhotoThumbUrl(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_PHOTO_THUMB_URL))); + item.setPhotoLocal(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_PHOTO_LOCAL))); return item; } @@ -138,6 +140,8 @@ public class Db { public static final String COLUMN_PHOTO_THUMBNAIL_URL = "photo_thumbnail_url"; public static final String COLUMN_PHOTO_THUMBNAIL_LOCAL = "photo_thumbnail_local"; public static final String COLUMN_LINE_NUMBER = "line_num"; + public static final String COLUMN_PACKED_QTY = "packed_qty"; + public static final String COLUMN_ACTIVE_QTY = "active_qty"; public static final String CREATE = @@ -151,6 +155,8 @@ public class Db { COLUMN_PHOTO_THUMB_LOCAL + " TEXT, " + COLUMN_PHOTO_THUMBNAIL_URL + " TEXT, " + COLUMN_LINE_NUMBER + " INTEGER, " + + COLUMN_PACKED_QTY + " INTEGER, " + + COLUMN_ACTIVE_QTY + " INTEGER, " + COLUMN_PHOTO_THUMBNAIL_LOCAL + " TEXT" + " ); "; @@ -170,6 +176,7 @@ public class Db { values.put(COLUMN_PHOTO_THUMB_URL, set.getPhotoThumb()); values.put(COLUMN_PHOTO_THUMBNAIL_URL, set.getPhotoThumbnail()); values.put(COLUMN_LINE_NUMBER, lineNumber); + values.put(COLUMN_ACTIVE_QTY, items.size()); /* values.put(COLUMN_PHOTO_LOCAL, ""); values.put(COLUMN_PHOTO_THUMB_LOCAL, ""); @@ -194,6 +201,8 @@ public class Db { set.setPhotoThumb(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_PHOTO_THUMB_URL))); set.setPhotoThumbnail(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_PHOTO_THUMBNAIL_URL))); set.setLineNumber(cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_LINE_NUMBER))); + set.setPackedQty(cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_PACKED_QTY))); + set.setActiveQty(cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_ACTIVE_QTY))); return set; } diff --git a/app/src/main/java/hikapro/com/backpack/model/dao/Event.java b/app/src/main/java/hikapro/com/backpack/model/dao/Event.java index e4ada30..b120747 100644 --- a/app/src/main/java/hikapro/com/backpack/model/dao/Event.java +++ b/app/src/main/java/hikapro/com/backpack/model/dao/Event.java @@ -12,11 +12,15 @@ public interface Event { int SET_LOAD_ERROR = -0x1; int SET_REORDER_ERROR = -0x2; int SET_ITEMS_LOAD_ERROR = -0x3; + int SET_PACKED_LOAD_ERROR = -0x4; + int SET_UNPACK_ERROR = -0x5; int SET_LOAD_COMPLETED = 0x1; int SET_REORDER_COMPLETED = 0x2; int SET_ITEMS_LOAD_COMPLETED = 0x3; + int SET_PACKED_LOAD_COMPLETED = 0x4; + int SET_UNPACK_COMPLETED = 0x5; int ITEM_FROM_SET_ERROR = -0x14; @@ -25,6 +29,7 @@ public interface Event { int ITEM_PACK_ERROR = -0x17; int ITEM_UNPACK_ERROR = -0x18; int ITEM_CATEGORY_LOAD_ERROR = -0x19; + int ITEM_IMAGE_LOAD_ERROR = -0x1A; int ITEM_FROM_SET_DELETED = 0x14; int ITEM_INSERTED = 0x15; @@ -32,6 +37,8 @@ public interface Event { int ITEM_PACKED = 0x17; int ITEM_UNPACKED = 0x18; int ITEM_CATEGORY_LOAD_COMPLETED = 0x19; + int ITEM_IMAGE_LOAD_COMPLETED = 0x1A; + int MY_LIST_POST_ERROR = -0x28; int MY_LIST_ITEM_ADD_ERROR = -0x29; diff --git a/app/src/main/java/hikapro/com/backpack/model/dao/ImageDownloadHelper.java b/app/src/main/java/hikapro/com/backpack/model/dao/ImageDownloadHelper.java new file mode 100644 index 0000000..ebc2660 --- /dev/null +++ b/app/src/main/java/hikapro/com/backpack/model/dao/ImageDownloadHelper.java @@ -0,0 +1,145 @@ +package hikapro.com.backpack.model.dao; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.Uri; +import android.os.Environment; +import android.util.Log; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URL; +import java.net.URLConnection; + +import hikapro.com.backpack.App; + +/** + * Created by tariel on 04/05/16. + */ +public class ImageDownloadHelper { + + public static final String ITEMS_TAG = "items"; + private Context context; + + public ImageDownloadHelper() { + this.context = App.getAppContext(); + } + + public Bitmap loadImage(String netPath) { + Bitmap bitmap = null; + try { + URL url = new URL(netPath); + URLConnection conn = url.openConnection(); + bitmap = BitmapFactory.decodeStream(conn.getInputStream()); + } catch (Exception ex) { + Log.e(ITEMS_TAG, " File cannot be downloaded"); + } + return bitmap; + } + + public boolean existsExternal(String filename) { + boolean ret = false; + if (isExternalStorageReadable()) { + File directory = getDir(); + File file = new File(directory.getAbsoluteFile(), filename); + ret = file.exists(); + } + return ret; + } + public boolean existsInternal(String filename) { + boolean ret = false; + File file = createTempFile(filename); + if (file != null) { + ret = file.exists(); + } + return ret; + } + + private File createTempFile(String fileName) { + File file = null; + try { + file = File.createTempFile(fileName, null, context.getCacheDir()); + } catch (IOException e) { + Log.e(ITEMS_TAG, " Cannot obtain temp file"); + } + return file; + } + + public String generateFileName(String netPath) { + String ret = ""; + if (netPath != null && !netPath.isEmpty()) { + ret = Uri.parse(netPath).getLastPathSegment(); + } + return ret; + } + + public String saveImageInternal(String filename, Bitmap bitmap) { + File file = null; + FileOutputStream outputStream; + if (bitmap != null && !filename.isEmpty()) { + file = createTempFile(filename); + if (file != null) { + try { + outputStream = new FileOutputStream(file); + bitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream); + outputStream.flush(); + outputStream.close(); + } catch (Exception e) { + Log.e(ITEMS_TAG, " File cannot be saved"); + } + } + } + return file != null ? file.getAbsolutePath() : null; + } + + public String saveImageExternal(String filename, Bitmap bitmap) { + File file = null; + FileOutputStream outputStream; + if (isExternalStorageWritable()) { + if (bitmap != null && !filename.isEmpty()) { + File directory = getDir(); + file = new File(directory.getAbsoluteFile(), filename); + try { + outputStream = new FileOutputStream(file); + bitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream); + outputStream.flush(); + outputStream.close(); + } catch (Exception e) { + Log.e(ITEMS_TAG, " File cannot be saved"); + } + } + } + return file != null ? file.getAbsolutePath() : null; + } + + /* Checks if external storage is available for read and write */ + public boolean isExternalStorageWritable() { + String state = Environment.getExternalStorageState(); + if (Environment.MEDIA_MOUNTED.equals(state)) { + return true; + } + return false; + } + + /* Checks if external storage is available to at least read */ + public boolean isExternalStorageReadable() { + String state = Environment.getExternalStorageState(); + if (Environment.MEDIA_MOUNTED.equals(state) || + Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { + return true; + } + return false; + } + + private File getDir() { + // Get the directory for the app's private pictures directory. + File file = new File(context.getExternalFilesDir( + Environment.DIRECTORY_PICTURES), ITEMS_TAG); + if (!file.mkdirs()) { + Log.e(ITEMS_TAG, " Directory not created"); + } + return file; + } +} diff --git a/app/src/main/java/hikapro/com/backpack/model/entities/Item.java b/app/src/main/java/hikapro/com/backpack/model/entities/Item.java index 10adc19..dfe6d59 100644 --- a/app/src/main/java/hikapro/com/backpack/model/entities/Item.java +++ b/app/src/main/java/hikapro/com/backpack/model/entities/Item.java @@ -34,6 +34,8 @@ public class Item implements Comparable, Serializable { @Expose private String photoThumbUrl; + private String photoLocal; + public Item() { } @@ -104,6 +106,14 @@ public class Item implements Comparable, Serializable { this.photoThumbUrl = photoThumbUrl; } + public String getPhotoLocal() { + return photoLocal; + } + + public void setPhotoLocal(String photoLocal) { + this.photoLocal = photoLocal; + } + @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; diff --git a/app/src/main/java/hikapro/com/backpack/model/entities/Set.java b/app/src/main/java/hikapro/com/backpack/model/entities/Set.java index 194cb16..b1a4abd 100644 --- a/app/src/main/java/hikapro/com/backpack/model/entities/Set.java +++ b/app/src/main/java/hikapro/com/backpack/model/entities/Set.java @@ -32,6 +32,8 @@ public class Set implements Comparable, Serializable { private String photoThumbnail; private int lineNumber; + private int packedQty; + private int activeQty; public Set() { } @@ -101,6 +103,22 @@ public class Set implements Comparable, Serializable { this.lineNumber = lineNumber; } + public int getPackedQty() { + return packedQty; + } + + public void setPackedQty(int packedQty) { + this.packedQty = packedQty; + } + + public int getActiveQty() { + return activeQty; + } + + public void setActiveQty(int activeQty) { + this.activeQty = activeQty; + } + @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; diff --git a/app/src/main/java/hikapro/com/backpack/presenter/ItemDetailPresenter.java b/app/src/main/java/hikapro/com/backpack/presenter/ItemDetailPresenter.java index daffca3..8fe9a0a 100644 --- a/app/src/main/java/hikapro/com/backpack/presenter/ItemDetailPresenter.java +++ b/app/src/main/java/hikapro/com/backpack/presenter/ItemDetailPresenter.java @@ -1,6 +1,7 @@ package hikapro.com.backpack.presenter; import android.content.Context; +import android.graphics.Bitmap; import android.os.Bundle; import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.LinearLayoutManager; @@ -60,35 +61,6 @@ public class ItemDetailPresenter implements Presenter.ItemDetail { } // life cycle <-- - // recycler --> - - @Override - public int getItemsCount() { - return model.getCount(); - } - @Override - public void bindViewHolder(DetailViewHolder holder, int position) { - hikapro.com.backpack.model.entities.Item item = model.findItem(position); - holder.title.setText(item.getName()); - holder.description.setText(item.getDescription()); - holder.title.setOnClickListener(new android.view.View.OnClickListener() { - @Override - public void onClick(android.view.View view) { - showMessage("On detail click"); - } - }); - } - @Override - public DetailViewHolder createViewHolder(ViewGroup parent, int viewType) { - DetailViewHolder viewHolder; - android.view.View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_detail, - parent, false); - viewHolder = new DetailViewHolder(v); - return viewHolder; - } - - // recycler <-- - // process --> @Override @@ -110,6 +82,11 @@ public class ItemDetailPresenter implements Presenter.ItemDetail { this.model = model; } + @Override + public Model.Detail getModel() { + return model; + } + @Override public Item getCurrentItem() { return item; @@ -136,6 +113,11 @@ public class ItemDetailPresenter implements Presenter.ItemDetail { Toast.makeText(getView().getAppContext(), message, Toast.LENGTH_SHORT).show(); } + @Override + public void displayPicture(Bitmap bitmap) { + + + } // other impl <-- private View.ItemDetail getView() throws NullPointerException { diff --git a/app/src/main/java/hikapro/com/backpack/presenter/ItemListPresenter.java b/app/src/main/java/hikapro/com/backpack/presenter/ItemListPresenter.java index 1ee0ebb..77b98fe 100644 --- a/app/src/main/java/hikapro/com/backpack/presenter/ItemListPresenter.java +++ b/app/src/main/java/hikapro/com/backpack/presenter/ItemListPresenter.java @@ -1,5 +1,7 @@ package hikapro.com.backpack.presenter; +import android.app.ActionBar; +import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; @@ -7,6 +9,8 @@ import android.support.v7.widget.RecyclerView; import android.support.v7.widget.helper.ItemTouchHelper; import android.view.LayoutInflater; import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.TextView; import android.widget.Toast; import java.lang.ref.WeakReference; @@ -26,13 +30,17 @@ import hikapro.com.backpack.view.View; */ public class ItemListPresenter implements Presenter.ItemList { - private static final String BUNDLE_SET_LIST_KEY = "BUNDLE_SET_LIST_KEY"; + protected static final String BUNDLE_SET_LIST_KEY = "BUNDLE_SET_LIST_KEY"; - private WeakReference view; - private Model.Item model; - private Set set; - private ItemListAdapter adapter; - RecyclerView recycler; + protected WeakReference view; + protected Model.Item model; + protected Set set; + protected ItemListAdapter adapter; + protected RecyclerView recycler; + + private LinearLayout footer; + private TextView showPacked; + protected TextView packedCount; public ItemListPresenter() { this.adapter = new ItemListAdapter(this); @@ -51,9 +59,11 @@ public class ItemListPresenter implements Presenter.ItemList { } @Override public android.view.View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - /* + if (savedInstanceState != null) - set = (Set) savedInstanceState.getSerializable(BUNDLE_SET_LIST_KEY);*/ + set = (Set) savedInstanceState.getSerializable(BUNDLE_SET_LIST_KEY); + else + set = getView().getSet(); android.view.View view = inflater.inflate(R.layout.fragment_item_list, container, false); LinearLayoutManager llm = new LinearLayoutManager(getActivityContext()); recycler = (RecyclerView) view.findViewById(R.id.items_recycler); @@ -76,6 +86,32 @@ public class ItemListPresenter implements Presenter.ItemList { adapter.setUndoOn(true); model.executeQuery(); + footer = (LinearLayout) view.findViewById(R.id.item_list_footer); + packedCount = (TextView) footer.findViewById(R.id.footer_packed_count); + showPacked = (TextView) footer.findViewById(R.id.open_packed); + showPacked.setOnClickListener(new android.view.View.OnClickListener() { + @Override + public void onClick(android.view.View v) { + showPackedItems(); + } + }); + Activity activity = (Activity) getActivityContext(); + if (activity != null) { + ActionBar actionBar = activity.getActionBar(); + if (actionBar != null) { + actionBar.show(); + actionBar.setTitle(set.getName()); + } + } + /* + if ( model.getPackedQty() > 0) { + footer.setVisibility(android.view.View.VISIBLE); + String str = String.format("%s %d / %d", + getActivityContext().getResources().getString(R.string.packed), model.getPackedQty(), + model.getActiveItemsCount()); + packedCount.setText(str); + } + */ return view; } @Override @@ -94,12 +130,45 @@ public class ItemListPresenter implements Presenter.ItemList { } @Override - public void clickItem(int itemId) { + public void notifyItemPackStatusChanged() { + + setVisibility(); + Context context = getActivityContext(); + if (context != null) { + + String str = String.format("%s %d / %d", + context.getResources().getString(R.string.packed), + model.getPackedQty(), + model.getActiveItemsCount()); + packedCount.setText(str); + } + } + + @Override + public void setVisibility() { + if (model.getPackedQty() == model.getActiveItemsCount()) { + footer.setVisibility(android.view.View.VISIBLE); + } else if ( model.getPackedQty() > 0) { + footer.setVisibility(android.view.View.VISIBLE); + } else { + footer.setVisibility(android.view.View.GONE); + } + + } + + + private void showPackedItems () { + getView().showPackedItems(set); + } + + @Override + public void showDetails(int itemId) { Item item = model.findItem(itemId); if (item != null) getView().showItemDetail(item); else showMessage(String.format("Item with Id %d is not found.", itemId)); + } // process <-- @@ -143,7 +212,7 @@ public class ItemListPresenter implements Presenter.ItemList { // other impl <-- - private View.ItemList getView() throws NullPointerException { + protected View.ItemList getView() throws NullPointerException { if ( view != null ) return view.get(); else diff --git a/app/src/main/java/hikapro/com/backpack/presenter/PackedListPresenter.java b/app/src/main/java/hikapro/com/backpack/presenter/PackedListPresenter.java new file mode 100644 index 0000000..258c321 --- /dev/null +++ b/app/src/main/java/hikapro/com/backpack/presenter/PackedListPresenter.java @@ -0,0 +1,123 @@ +package hikapro.com.backpack.presenter; + +import android.app.Fragment; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.helper.ItemTouchHelper; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.TextView; + +import hikapro.com.backpack.R; +import hikapro.com.backpack.model.entities.Set; +import hikapro.com.backpack.presenter.adapters.PackedListAdapter; +import hikapro.com.backpack.presenter.adapters.helper.items.DividerDecoration; +import hikapro.com.backpack.presenter.adapters.helper.items.ItemSwipeCallback; +import hikapro.com.backpack.presenter.adapters.helper.items.StickyHeaderDecoration; + +/** + * Created by tariel on 13/05/16. + */ +public class PackedListPresenter extends ItemListPresenter { + + private TextView backToList; + private Button unpackButton; + + + public PackedListPresenter() { + this.adapter = new PackedListAdapter(this); + adapter.setHasStableIds(true); + adapter.setCheckAll(true); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + if (savedInstanceState != null) + set = (Set) savedInstanceState.getSerializable(BUNDLE_SET_LIST_KEY); + else + set = getView().getSet(); + android.view.View view = inflater.inflate(R.layout.fragment_packed_list, container, false); + LinearLayoutManager llm = new LinearLayoutManager(getActivityContext()); + recycler = (RecyclerView) view.findViewById(R.id.items_recycler); + recycler.setLayoutManager(llm); + recycler.setAdapter(adapter); + + final StickyHeaderDecoration decoration = new StickyHeaderDecoration(adapter); + recycler.addItemDecoration(decoration); + recycler.addItemDecoration(new DividerDecoration(getActivityContext())); + adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() { + @Override + public void onChanged() { + decoration.invalidateHeaders(); + } + }); + ItemSwipeCallback itemSwipeCallback = new ItemSwipeCallback(0, ItemTouchHelper.LEFT, adapter, getActivityContext()); + + ItemTouchHelper itemTouchHelper = new ItemTouchHelper(itemSwipeCallback); + itemTouchHelper.attachToRecyclerView(recycler); + adapter.setUndoOn(true); + + model.executeQuery(); + + backToList = (TextView) view.findViewById(R.id.back_to_list); + packedCount = (TextView) view.findViewById(R.id.header_packed_count); + unpackButton = (Button) view.findViewById(R.id.unpack_button); + + if (model.getPackedQty() == model.getActiveItemsCount()) { + backToList.setVisibility(View.INVISIBLE); + packedCount.setVisibility(View.INVISIBLE); + unpackButton.setVisibility(View.VISIBLE); + } else { + backToList.setVisibility(View.VISIBLE); + packedCount.setVisibility(View.VISIBLE); + unpackButton.setVisibility(View.INVISIBLE); + + } + + unpackButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + model.unpackSet(set.getId()); + } + }); + + backToList.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Fragment fragment = (Fragment) getView(); + if (fragment != null) + fragment.getFragmentManager().popBackStack(); + } + }); + + /* + String str = String.format("%s %d / %d", + getActivityContext().getResources().getString(R.string.packed), + model.getPackedQty(), model.getActiveItemsCount()); + packedCount.setText(str); + */ + return view; + } + + + @Override + public void setVisibility() { + if (model.getPackedQty() == 0) { + packedCount.setVisibility(View.GONE); + unpackButton.setVisibility(View.GONE); + backToList.setVisibility(View.VISIBLE); + } else if (model.getPackedQty() == model.getActiveItemsCount()) { + packedCount.setVisibility(View.GONE); + unpackButton.setVisibility(View.VISIBLE); + backToList.setVisibility(View.GONE); + } else { + packedCount.setVisibility(View.VISIBLE); + unpackButton.setVisibility(View.GONE); + backToList.setVisibility(View.VISIBLE); + } + } +} diff --git a/app/src/main/java/hikapro/com/backpack/presenter/Presenter.java b/app/src/main/java/hikapro/com/backpack/presenter/Presenter.java index 347c886..fee3285 100644 --- a/app/src/main/java/hikapro/com/backpack/presenter/Presenter.java +++ b/app/src/main/java/hikapro/com/backpack/presenter/Presenter.java @@ -1,6 +1,7 @@ package hikapro.com.backpack.presenter; import android.content.Context; +import android.graphics.Bitmap; import android.os.Bundle; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; @@ -18,20 +19,22 @@ import hikapro.com.backpack.view.recycler.SetViewHolder; */ public interface Presenter { + int ADD_TO_BACKSTACK = 0b0001; + int TRANSITION_X = 0b0010; + int TRANSITION_Y = 0b0100; + interface Base { Context getAppContext(); Context getActivityContext(); } interface SetList extends Base { - SetViewHolder createViewHolder(ViewGroup parent, int viewType); - void bindViewHolder(SetViewHolder holder, int position); - int getSetsCount(); - void clickSet(int setId); + void showItemList(Set set); void onDestroy(boolean isChangingConfiguration); android.view.View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState); void setView(hikapro.com.backpack.view.View.SetList view); void setModel(Model.Set model); + Model.Set getModel(); void notifyDataSetChanged(); void showMessage(String message); @@ -49,28 +52,28 @@ public interface Presenter { void setModel(Model.Item model); Model.Item getModel(); void notifyDataSetChanged(); + void notifyItemPackStatusChanged(); + void setVisibility(); Set getCurrentSet(); void showMessage(String message); void onSaveInstanceState(Bundle outState); - void clickItem(int itemId); + void showDetails(int itemId); void filter(String query); } interface ItemDetail extends Base { void setView(hikapro.com.backpack.view.View.ItemDetail view); void setModel(Model.Detail model); + Model.Detail getModel(); void notifyDataSetChanged(); void showMessage(String message); - int getItemsCount(); - void bindViewHolder(DetailViewHolder holder, int position); - DetailViewHolder createViewHolder(ViewGroup parent, int viewType); void onDestroy(boolean isChangingConfiguration); android.view.View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState); void onSaveInstanceState(Bundle outState); Item getCurrentItem(); - - + void displayPicture(Bitmap bitmap); } + } diff --git a/app/src/main/java/hikapro/com/backpack/presenter/SetListPresenter.java b/app/src/main/java/hikapro/com/backpack/presenter/SetListPresenter.java index 02604a1..f355b35 100644 --- a/app/src/main/java/hikapro/com/backpack/presenter/SetListPresenter.java +++ b/app/src/main/java/hikapro/com/backpack/presenter/SetListPresenter.java @@ -1,5 +1,6 @@ package hikapro.com.backpack.presenter; +import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.support.v7.widget.DefaultItemAnimator; @@ -82,66 +83,17 @@ public class SetListPresenter implements Presenter.SetList { ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(adapter); mItemTouchHelper = new ItemTouchHelper(callback); mItemTouchHelper.attachToRecyclerView(setRecycler); + Activity activity = (Activity) getActivityContext(); + if (activity != null) + activity.getActionBar().hide(); return view; } // life cycle <-- - // recycler --> - - @Override - public SetViewHolder createViewHolder(ViewGroup parent, int viewType) { - SetViewHolder viewHolder; - android.view.View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.set_card, - parent, false); - viewHolder = new SetViewHolder(v); - return viewHolder; - } - @Override - public void bindViewHolder(final SetViewHolder holder, int position) { - - final hikapro.com.backpack.model.entities.Set set = model.getSetByPosition(position); - holder.textView.setText(set.getName()); - holder.cardView.setOnClickListener(new android.view.View.OnClickListener() { - @Override - public void onClick(android.view.View v) { - if (getView() != null) - getView().showItemList(set); - else - showMessage("There is no view in presenter"); - } - }); - - - //GLM_add_resources_SetList - holder.cardView.setOnLongClickListener(new android.view.View.OnLongClickListener() { - @Override - public boolean onLongClick(android.view.View v) { - - mDragStartListener.onStartDrag(holder); - return false; - } - }); - } - @Override - public int getSetsCount() { - return model.getSetsCount(); - } - - // recycler <-- - // process --> - @Override - public void clickSet(int setId) { - Set set = model.findSet(setId); - if (set != null) { - getView().showItemList(set); - } else { - showMessage("Set not found!"); - } - } @Override public void notifyDataSetChanged() { adapter.notifyDataSetChanged(); @@ -176,6 +128,12 @@ public class SetListPresenter implements Presenter.SetList { public void setModel(Model.Set model) { this.model = model; } + + @Override + public Model.Set getModel() { + return model; + } + @Override public void showMessage(String message) { Toast.makeText(getView().getAppContext(), message, Toast.LENGTH_SHORT).show(); @@ -195,4 +153,15 @@ public class SetListPresenter implements Presenter.SetList { public void onStartDrag(RecyclerView.ViewHolder viewHolder) { mItemTouchHelper.startDrag(viewHolder); } + + public void showItemList(Set set) { + if (getView() != null) + getView().showItemList(set); + else + showMessage("There is no view in presenter"); + } + + public void onLongClick(SetViewHolder holder) { + mDragStartListener.onStartDrag(holder); + } } diff --git a/app/src/main/java/hikapro/com/backpack/presenter/adapters/ItemDetailAdapter.java b/app/src/main/java/hikapro/com/backpack/presenter/adapters/ItemDetailAdapter.java index bbf1a00..2a44c6e 100644 --- a/app/src/main/java/hikapro/com/backpack/presenter/adapters/ItemDetailAdapter.java +++ b/app/src/main/java/hikapro/com/backpack/presenter/adapters/ItemDetailAdapter.java @@ -1,8 +1,12 @@ package hikapro.com.backpack.presenter.adapters; +import android.graphics.Bitmap; import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; import android.view.ViewGroup; +import hikapro.com.backpack.R; +import hikapro.com.backpack.model.Model; import hikapro.com.backpack.presenter.Presenter; import hikapro.com.backpack.view.recycler.DetailViewHolder; @@ -12,7 +16,6 @@ import hikapro.com.backpack.view.recycler.DetailViewHolder; public class ItemDetailAdapter extends RecyclerView.Adapter { private Presenter.ItemDetail presenter; - private int itemId; public ItemDetailAdapter(Presenter.ItemDetail presenter) { this.presenter = presenter; @@ -20,21 +23,33 @@ public class ItemDetailAdapter extends RecyclerView.Adapter { @Override public int getItemCount() { - return presenter.getItemsCount(); + return presenter.getModel().getCount(); } @Override public void onBindViewHolder(DetailViewHolder holder, int position) { - presenter.bindViewHolder(holder, position); - + hikapro.com.backpack.model.entities.Item item = presenter.getModel().findItem(position); + holder.title.setText(item.getName()); + holder.description.setText(item.getDescription()); + Bitmap bitmap = presenter.getModel().getPicture(); + if (bitmap != null) + holder.photo.setImageBitmap(bitmap); + holder.title.setOnClickListener(new android.view.View.OnClickListener() { + @Override + public void onClick(android.view.View view) { + presenter.showMessage("On detail click"); + } + }); } @Override public DetailViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - return presenter.createViewHolder(parent, viewType); + DetailViewHolder viewHolder; + android.view.View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_detail, + parent, false); + viewHolder = new DetailViewHolder(v); + return viewHolder; } - public void setItemId(int id) { - this.itemId = id; - } + } diff --git a/app/src/main/java/hikapro/com/backpack/presenter/adapters/ItemListAdapter.java b/app/src/main/java/hikapro/com/backpack/presenter/adapters/ItemListAdapter.java index 230c723..0842b44 100644 --- a/app/src/main/java/hikapro/com/backpack/presenter/adapters/ItemListAdapter.java +++ b/app/src/main/java/hikapro/com/backpack/presenter/adapters/ItemListAdapter.java @@ -10,10 +10,8 @@ import android.view.ViewGroup; import java.util.HashMap; import hikapro.com.backpack.R; -import hikapro.com.backpack.model.Model; import hikapro.com.backpack.model.entities.Category; import hikapro.com.backpack.model.entities.Item; -import hikapro.com.backpack.presenter.ItemListPresenter; import hikapro.com.backpack.presenter.Presenter; import hikapro.com.backpack.presenter.adapters.helper.items.StickyHeaderAdapter; import hikapro.com.backpack.view.recycler.HeaderViewHolder; @@ -30,6 +28,7 @@ public class ItemListAdapter extends RecyclerView.Adapter implem private Handler handler = new Handler(); // hanlder for running delayed runnables HashMap pendingRunables = new HashMap<>(); // map of items to pending runnables, so we can cancel a removal if need be private Presenter.ItemList presenter; + private boolean checkAll; public ItemListAdapter(Presenter.ItemList presenter) { this.presenter = presenter; @@ -43,7 +42,8 @@ public class ItemListAdapter extends RecyclerView.Adapter implem @Override public long getItemId(int position) { - return presenter.getModel().getItemByPosition(position).getId(); + long ret = presenter.getModel().getItemId(position); + return ret; } @Override @@ -53,7 +53,7 @@ public class ItemListAdapter extends RecyclerView.Adapter implem if (presenter.getModel().isPendingRemoval(item)) { // we need to show the "undo" state of the row holder.itemView.setBackgroundColor(Color.RED); - holder.title.setVisibility(View.GONE); + holder.checkBox.setVisibility(View.GONE); holder.undoButton.setVisibility(View.VISIBLE); holder.undoButton.setOnClickListener(new View.OnClickListener() { @Override @@ -68,16 +68,28 @@ public class ItemListAdapter extends RecyclerView.Adapter implem } }); } else { - holder.title.setVisibility(View.VISIBLE); - holder.title.setText(item.getName()); + holder.checkBox.setVisibility(View.VISIBLE); + holder.checkBox.setChecked(checkAll); + holder.checkBox.setText(item.getName() + " " + item.getId() + " pos " + position);//TODO del holder.id = item.getId(); - holder.title.setOnClickListener(new android.view.View.OnClickListener() { + holder.checkBox.setOnClickListener(new android.view.View.OnClickListener() { @Override public void onClick(View v) { - presenter.clickItem(holder.id); + if (holder.checkBox.isChecked()) { + pack(holder.id, position); + // presenter.packItem(); TODO wtf + } else { + unpack(holder.id, position); + // presenter.unpackItem(); TODO wtf + } + } + }); + holder.infoButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + presenter.showDetails(holder.id); } }); - holder.categoryId = item.getCategory(); holder.itemView.setBackgroundColor(0x33FF99); holder.undoButton.setVisibility(View.GONE); holder.undoButton.setOnClickListener(null); @@ -118,11 +130,6 @@ public class ItemListAdapter extends RecyclerView.Adapter implem notifyDataSetChanged(); } - @Override - public void setHasStableIds(boolean hasStableIds) { - super.setHasStableIds(hasStableIds); - } - @Override public long getHeaderId(int position) { /*if (position == 0) { @@ -184,4 +191,26 @@ public class ItemListAdapter extends RecyclerView.Adapter implem return presenter.getModel().isPendingRemoval(item); } + public void pack(int itemId, int position) { + presenter.getModel().packItem(itemId); + notifyDataSetChanged(); + /* + notifyItemRemoved(position); + notifyItemRangeRemoved(position, getItemCount()); + */ + } + + public void unpack(int itemId, int position) { + presenter.getModel().unpackItem(itemId); + //notifyItemRemoved(position); + notifyDataSetChanged(); + } + + public void unpackAll() { + + } + + public void setCheckAll(boolean checkAll) { + this.checkAll = checkAll; + } } diff --git a/app/src/main/java/hikapro/com/backpack/presenter/adapters/PackedListAdapter.java b/app/src/main/java/hikapro/com/backpack/presenter/adapters/PackedListAdapter.java new file mode 100644 index 0000000..2d862b0 --- /dev/null +++ b/app/src/main/java/hikapro/com/backpack/presenter/adapters/PackedListAdapter.java @@ -0,0 +1,14 @@ +package hikapro.com.backpack.presenter.adapters; + +import hikapro.com.backpack.presenter.Presenter; +import hikapro.com.backpack.presenter.adapters.ItemListAdapter; + +/** + * Created by tariel on 12/05/16. + */ +public class PackedListAdapter extends ItemListAdapter { + + public PackedListAdapter(Presenter.ItemList presenter) { + super(presenter); + } +} diff --git a/app/src/main/java/hikapro/com/backpack/presenter/adapters/SetListAdapter.java b/app/src/main/java/hikapro/com/backpack/presenter/adapters/SetListAdapter.java index 5293c81..aa78956 100644 --- a/app/src/main/java/hikapro/com/backpack/presenter/adapters/SetListAdapter.java +++ b/app/src/main/java/hikapro/com/backpack/presenter/adapters/SetListAdapter.java @@ -1,8 +1,11 @@ package hikapro.com.backpack.presenter.adapters; import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; import android.view.ViewGroup; +import hikapro.com.backpack.R; import hikapro.com.backpack.presenter.SetListPresenter; import hikapro.com.backpack.presenter.adapters.helper.sets.ItemTouchHelperAdapter; import hikapro.com.backpack.view.recycler.SetViewHolder; @@ -13,24 +16,59 @@ import hikapro.com.backpack.view.recycler.SetViewHolder; public class SetListAdapter extends RecyclerView.Adapter implements ItemTouchHelperAdapter{ private SetListPresenter presenter; + private String rightBracket; public SetListAdapter(SetListPresenter presenter) { this.presenter = presenter; } @Override - public void onBindViewHolder(SetViewHolder holder, int position) { - presenter.bindViewHolder(holder, position); + public void onBindViewHolder(final SetViewHolder holder, int position) { + + final hikapro.com.backpack.model.entities.Set set = presenter.getModel().getSetByPosition(position); + + if (rightBracket == null || rightBracket.isEmpty()) { + + if (presenter.getActivityContext() != null) + this.rightBracket = presenter.getActivityContext().getResources(). + getString(R.string.right_angle_bracket); + else + this.rightBracket = ""; + } + + holder.textView.setText(set.getName() + " " + rightBracket); + String info = String.format("%s %d / %d", + presenter.getActivityContext().getResources().getString(R.string.packed), + set.getPackedQty(), + set.getActiveQty()); + holder.setInfo.setText(info); + holder.cardView.setOnClickListener(new android.view.View.OnClickListener() { + @Override + public void onClick(android.view.View v) { + presenter.showItemList(set); + } + }); + holder.cardView.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + presenter.onLongClick(holder); + return false; + } + }); } @Override public SetViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - return presenter.createViewHolder(parent, viewType); + SetViewHolder viewHolder; + android.view.View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.set_card, + parent, false); + viewHolder = new SetViewHolder(v); + return viewHolder; } @Override public int getItemCount() { - return presenter.getSetsCount(); + return presenter.getModel().getSetsCount(); } //GLM_add_resources_SetList diff --git a/app/src/main/java/hikapro/com/backpack/view/View.java b/app/src/main/java/hikapro/com/backpack/view/View.java index 45148c1..5d51876 100644 --- a/app/src/main/java/hikapro/com/backpack/view/View.java +++ b/app/src/main/java/hikapro/com/backpack/view/View.java @@ -26,6 +26,7 @@ public interface View { interface ItemList extends Base { void showItemDetail(Item item); + void showPackedItems(Set set); void setPresenter(Presenter.ItemList presenter); Set getSet(); } @@ -33,9 +34,11 @@ public interface View { void setPresenter(Presenter.ItemDetail presenter); Item getItem(); } + interface ActivityCallback { void startSetListFragment(); void startItemListFragment(Set set); + void startPackedListFragment(Set set); void startItemDetailFragment(Item item); } diff --git a/app/src/main/java/hikapro/com/backpack/view/fragments/ItemDetailFragment.java b/app/src/main/java/hikapro/com/backpack/view/fragments/ItemDetailFragment.java index 9673463..b7c3de9 100644 --- a/app/src/main/java/hikapro/com/backpack/view/fragments/ItemDetailFragment.java +++ b/app/src/main/java/hikapro/com/backpack/view/fragments/ItemDetailFragment.java @@ -71,52 +71,52 @@ public class ItemDetailFragment extends Fragment implements hikapro.com.backpack public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment - View view = presenter.onCreateView(inflater, container, savedInstanceState); presenter.setView(this); - Log.i(this.toString(), "onCreateView"); + View view = presenter.onCreateView(inflater, container, savedInstanceState); + Log.i(this.toString(), " onCreateView"); return view; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - Log.i(this.toString(), "onActivityCreated"); + Log.i(this.toString(), " onActivityCreated"); } @Override public void onStart() { super.onStart(); - Log.i(this.toString(), "onStart"); + Log.i(this.toString(), " onStart"); } @Override public void onResume() { super.onResume(); - Log.i(this.toString(), "onResume"); + Log.i(this.toString(), " onResume"); } @Override public void onStop() { super.onStop(); - Log.i(this.toString(), "onStop"); + Log.i(this.toString(), " onStop"); } @Override public void onDestroyView() { super.onDestroyView(); presenter.onDestroy(true); // TODO isChangingConfigurations - Log.i(this.toString(), "onDestroyView"); + Log.i(this.toString(), " onDestroyView"); } @Override public void onDestroy() { super.onDestroy(); presenter.onDestroy(false); // TODO isChangingConfigurations - Log.i(this.toString(), "onDestroy"); + Log.i(this.toString(), " onDestroy"); } @Override public void onDetach() { super.onDetach(); - Log.i(this.toString(), "onDetach"); + Log.i(this.toString(), " onDetach"); } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); - Log.i(this.toString(), "onSaveInstanceState"); + Log.i(this.toString(), " onSaveInstanceState"); } // life cycle <-- diff --git a/app/src/main/java/hikapro/com/backpack/view/fragments/ItemListFragment.java b/app/src/main/java/hikapro/com/backpack/view/fragments/ItemListFragment.java index ccb05a8..ae1900d 100644 --- a/app/src/main/java/hikapro/com/backpack/view/fragments/ItemListFragment.java +++ b/app/src/main/java/hikapro/com/backpack/view/fragments/ItemListFragment.java @@ -25,7 +25,7 @@ import hikapro.com.backpack.presenter.Presenter; public class ItemListFragment extends Fragment implements hikapro.com.backpack.view.View.ItemList, SearchView.OnQueryTextListener { - private static final String BUNDLE_SET_KEY = "BUNDLE_SET_KEY"; + protected static final String BUNDLE_SET_KEY = "BUNDLE_SET_KEY"; private hikapro.com.backpack.view.View.ActivityCallback activityCallback; private Presenter.ItemList presenter; @@ -33,7 +33,7 @@ public class ItemListFragment extends Fragment implements hikapro.com.backpack.v // Required empty public constructor } - protected static ItemListFragment construct() { + private static ItemListFragment construct() { return new ItemListFragment(); } @@ -70,7 +70,24 @@ public class ItemListFragment extends Fragment implements hikapro.com.backpack.v @Override public boolean onOptionsItemSelected(MenuItem item) { - return super.onOptionsItemSelected(item); + boolean ret; + switch (item.getItemId()) { + case R.id.action_share : + Toast.makeText(getActivityContext(), "Share", Toast.LENGTH_SHORT).show(); + ret = true; + break; + case R.id.action_unpack_my_bag : + Toast.makeText(getActivityContext(), "Unpack my bag", Toast.LENGTH_SHORT).show(); + ret = true; + break; + case R.id.action_restore_to_default : + Toast.makeText(getActivityContext(), "Restore to default", Toast.LENGTH_SHORT).show(); + ret = true; + break; + default: + ret = super.onOptionsItemSelected(item); + } + return ret; } // life cycle --> @@ -93,13 +110,13 @@ public class ItemListFragment extends Fragment implements hikapro.com.backpack.v throw new ClassCastException(activity.toString() + " must implement activityCallback"); } - Log.i(this.toString(), "onAttach"); + Log.i(this.toString(), " onAttach"); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); - Log.i(this.toString(), "onCreate"); + Log.i(this.toString(), " onCreate"); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, @@ -107,50 +124,51 @@ public class ItemListFragment extends Fragment implements hikapro.com.backpack.v // Inflate the layout for this fragment presenter.setView(this); View view = presenter.onCreateView(inflater, container, savedInstanceState); - Log.i(this.toString(), "onCreateView"); + Log.i(this.toString(), " onCreateView"); return view; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - Log.i(this.toString(), "onActivityCreated"); + Log.i(this.toString(), " onActivityCreated"); } @Override public void onStart() { super.onStart(); - Log.i(this.toString(), "onStart"); + Log.i(this.toString(), " onStart"); } @Override public void onResume() { super.onResume(); - Log.i(this.toString(), "onResume"); + Log.i(this.toString(), " onResume"); } @Override public void onStop() { super.onStop(); - Log.i(this.toString(), "onStop"); + Log.i(this.toString(), " onStop"); } @Override public void onDestroyView() { super.onDestroyView(); presenter.onDestroy(true); // TODO isChangingConfigurations - Log.i(this.toString(), "onDestroyView"); + Log.i(this.toString(), " onDestroyView"); } @Override public void onDestroy() { super.onDestroy(); presenter.onDestroy(false); // TODO isChangingConfigurations - Log.i(this.toString(), "onDestroy"); + Log.i(this.toString(), " onDestroy"); } @Override public void onDetach() { super.onDetach(); - Log.i(this.toString(), "onDetach"); + Log.i(this.toString(), " onDetach"); } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); - Log.i(this.toString(), "onSaveInstanceState"); + presenter.onSaveInstanceState(outState); + Log.i(this.toString(), " onSaveInstanceState"); } // life cycle <-- @@ -160,6 +178,11 @@ public class ItemListFragment extends Fragment implements hikapro.com.backpack.v activityCallback.startItemDetailFragment(item); } + @Override + public void showPackedItems(Set set) { + activityCallback.startPackedListFragment(set); + } + @Override public void setPresenter(Presenter.ItemList presenter) { this.presenter = presenter; diff --git a/app/src/main/java/hikapro/com/backpack/view/fragments/PackedListFragment.java b/app/src/main/java/hikapro/com/backpack/view/fragments/PackedListFragment.java new file mode 100644 index 0000000..69e4d18 --- /dev/null +++ b/app/src/main/java/hikapro/com/backpack/view/fragments/PackedListFragment.java @@ -0,0 +1,27 @@ +package hikapro.com.backpack.view.fragments; + +import android.os.Bundle; + +import hikapro.com.backpack.model.entities.Set; + +/** + * Created by tariel on 12/05/16. + */ +public class PackedListFragment extends ItemListFragment { + + public PackedListFragment() { + } + + private static PackedListFragment construct() { + return new PackedListFragment(); + } + + public static PackedListFragment newFromSet(Set set) { + PackedListFragment ret = PackedListFragment.construct(); + Bundle args = new Bundle(); + args.putSerializable(BUNDLE_SET_KEY, set); + ret.setArguments(args); + return ret; + } + +} diff --git a/app/src/main/java/hikapro/com/backpack/view/recycler/ItemViewHolder.java b/app/src/main/java/hikapro/com/backpack/view/recycler/ItemViewHolder.java index b448f3f..618f83a 100644 --- a/app/src/main/java/hikapro/com/backpack/view/recycler/ItemViewHolder.java +++ b/app/src/main/java/hikapro/com/backpack/view/recycler/ItemViewHolder.java @@ -3,6 +3,8 @@ package hikapro.com.backpack.view.recycler; import android.support.v7.widget.RecyclerView; import android.view.View; import android.widget.Button; +import android.widget.CheckBox; +import android.widget.ImageButton; import android.widget.TextView; import hikapro.com.backpack.R; @@ -14,9 +16,9 @@ import hikapro.com.backpack.R; public class ItemViewHolder extends RecyclerView.ViewHolder { public int id; - public int categoryId; - public TextView title; - public Button undoButton; + public CheckBox checkBox; + public Button undoButton; + public ImageButton infoButton; public ItemViewHolder(View v) { super(v); @@ -24,7 +26,9 @@ public class ItemViewHolder extends RecyclerView.ViewHolder { } private void setupViews(View view) { - title = (TextView) view.findViewById(R.id.item_txt); + infoButton = (ImageButton) view.findViewById(R.id.info_button); + checkBox = (CheckBox) view.findViewById(R.id.item_checkbox); undoButton = (Button) view.findViewById(R.id.undo_button); } + } diff --git a/app/src/main/java/hikapro/com/backpack/view/recycler/SetViewHolder.java b/app/src/main/java/hikapro/com/backpack/view/recycler/SetViewHolder.java index ed82162..c54d2cd 100644 --- a/app/src/main/java/hikapro/com/backpack/view/recycler/SetViewHolder.java +++ b/app/src/main/java/hikapro/com/backpack/view/recycler/SetViewHolder.java @@ -17,6 +17,7 @@ public class SetViewHolder extends RecyclerView.ViewHolder implements ItemTouchH public CardView cardView; public TextView textView; + public TextView setInfo; //GLM_add_resources_SetList private View view; @@ -24,16 +25,13 @@ public class SetViewHolder extends RecyclerView.ViewHolder implements ItemTouchH public SetViewHolder(View v) { super(v); - // - this.view = v; - - // setupViews(v); } private void setupViews(View view) { - cardView = (CardView) view.findViewById(R.id.card_view_set); - textView = (TextView) view.findViewById(R.id.set_text); + cardView = (CardView) view.findViewById(R.id.card_view_set); + textView = (TextView) view.findViewById(R.id.set_text); + setInfo = (TextView) view.findViewById(R.id.set_info); this.view = view; drawable = view.getBackground(); diff --git a/app/src/main/res/animator/slide_in_bottom_y.xml b/app/src/main/res/animator/slide_in_bottom_y.xml new file mode 100644 index 0000000..53ea453 --- /dev/null +++ b/app/src/main/res/animator/slide_in_bottom_y.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/animator/slide_in_left_x.xml b/app/src/main/res/animator/slide_in_left_x.xml new file mode 100644 index 0000000..f8c7553 --- /dev/null +++ b/app/src/main/res/animator/slide_in_left_x.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/animator/slide_in_right_x.xml b/app/src/main/res/animator/slide_in_right_x.xml new file mode 100644 index 0000000..05199a6 --- /dev/null +++ b/app/src/main/res/animator/slide_in_right_x.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/animator/slide_in_top_y.xml b/app/src/main/res/animator/slide_in_top_y.xml new file mode 100644 index 0000000..7fd641f --- /dev/null +++ b/app/src/main/res/animator/slide_in_top_y.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/animator/slide_out_bottom_y.xml b/app/src/main/res/animator/slide_out_bottom_y.xml new file mode 100644 index 0000000..5fc7d09 --- /dev/null +++ b/app/src/main/res/animator/slide_out_bottom_y.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/animator/slide_out_left_x.xml b/app/src/main/res/animator/slide_out_left_x.xml new file mode 100644 index 0000000..a13ab18 --- /dev/null +++ b/app/src/main/res/animator/slide_out_left_x.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/animator/slide_out_right_x.xml b/app/src/main/res/animator/slide_out_right_x.xml new file mode 100644 index 0000000..184d522 --- /dev/null +++ b/app/src/main/res/animator/slide_out_right_x.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/animator/slide_out_top_y.xml b/app/src/main/res/animator/slide_out_top_y.xml new file mode 100644 index 0000000..64894c7 --- /dev/null +++ b/app/src/main/res/animator/slide_out_top_y.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-hdpi/ic_add_white_36dp.png b/app/src/main/res/drawable-hdpi/ic_add_white_36dp.png new file mode 100644 index 0000000..8630f40 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_add_white_36dp.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_info_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_info_black_24dp.png new file mode 100644 index 0000000..da56077 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_info_black_24dp.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_add_white_36dp.png b/app/src/main/res/drawable-xhdpi/ic_add_white_36dp.png new file mode 100644 index 0000000..0fdced8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_add_white_36dp.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_info_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_info_black_24dp.png new file mode 100644 index 0000000..46ed12a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_info_black_24dp.png differ diff --git a/app/src/main/res/drawable/ic_add_white_36dp.png b/app/src/main/res/drawable/ic_add_white_36dp.png new file mode 100644 index 0000000..694179b Binary files /dev/null and b/app/src/main/res/drawable/ic_add_white_36dp.png differ diff --git a/app/src/main/res/drawable/ic_info_black_24dp.png b/app/src/main/res/drawable/ic_info_black_24dp.png new file mode 100644 index 0000000..da56077 Binary files /dev/null and b/app/src/main/res/drawable/ic_info_black_24dp.png differ diff --git a/app/src/main/res/layout/footer.xml b/app/src/main/res/layout/footer.xml new file mode 100644 index 0000000..d9885a0 --- /dev/null +++ b/app/src/main/res/layout/footer.xml @@ -0,0 +1,26 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_item_list.xml b/app/src/main/res/layout/fragment_item_list.xml index ca43fc4..a3ce8f2 100644 --- a/app/src/main/res/layout/fragment_item_list.xml +++ b/app/src/main/res/layout/fragment_item_list.xml @@ -1,14 +1,48 @@ - + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:animateLayoutChanges="true"> - + + + + + - + android:orientation="vertical" + android:id="@+id/item_list_footer" + android:layout_gravity="bottom" + android:visibility="gone" + android:background="#80968AA7"> + + + + diff --git a/app/src/main/res/layout/fragment_packed_list.xml b/app/src/main/res/layout/fragment_packed_list.xml new file mode 100644 index 0000000..f238f47 --- /dev/null +++ b/app/src/main/res/layout/fragment_packed_list.xml @@ -0,0 +1,66 @@ + + + + + + + +