From: kenstir Date: Sat, 28 Dec 2013 22:49:56 +0000 (-0500) Subject: Global rename of misnamed org.evergreen.android -> org.evergreen_ils X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=14a271f8d9d95078d4ff105865bab43c1ac1d446;p=working%2FEvergreen.git Global rename of misnamed org.evergreen.android -> org.evergreen_ils evergreen.org is a church, evergreen-ils.org is library software --- diff --git a/Open-ILS/src/Android/README b/Open-ILS/src/Android/README index 213533a875..616b7a0d1c 100644 --- a/Open-ILS/src/Android/README +++ b/Open-ILS/src/Android/README @@ -19,9 +19,9 @@ Project relies on the following libraries : 2.Project structure : =================================================================== -Packages are under the root package org.evergreen.android : +Packages are under the root package org.evergreen_ils : - - org.evergreen.android.accountAccess: + - org.evergreen_ils.accountAccess: accountAccess.holds accountAccess.fines accountAccess.bookbags @@ -29,31 +29,31 @@ Packages are under the root package org.evergreen.android : This package handles the my account administration panel. In every subpackage the classes for the specific category are placed inside it. - - org.evergreen.android.barcodescan: + - org.evergreen_ils.barcodescan: This package represents the barcode scan part of the project. It has a camera AR view class which helps scan the barcode. The class is limited for scanning 1D barcodes like UPC and EAN type barcodes. - - org.evergreen.android.database + - org.evergreen_ils.database This package contains the Database Manager class that is used to persist classes into SQLite memory. - - org.evergreen.android.globals + - org.evergreen_ils.globals This package contains global configuration classes and utils methods and functions used within the project - - org.evergreen.android.searchCatalog + - org.evergreen_ils.searchCatalog This package is used for the search option of the application. - - org.evergreen.android.services + - org.evergreen_ils.services This package contains background services and broadcast receivers used for settings notifications on items checkout expiration. - - org.evergreen.android.utils.ui + - org.evergreen_ils.utils.ui Classes for fragment uses. Some of them are not used in the project but can become useful. - - org.evergreen.android.views + - org.evergreen_ils.views Some global application views like the Splashscreen, ApplicationSettings, MyAccountDashboard or the ConfigureApplication view. diff --git a/Open-ILS/src/Android/core/AndroidManifest.xml b/Open-ILS/src/Android/core/AndroidManifest.xml index f6d03ff4c8..95a42e16a6 100644 --- a/Open-ILS/src/Android/core/AndroidManifest.xml +++ b/Open-ILS/src/Android/core/AndroidManifest.xml @@ -1,6 +1,6 @@ @@ -37,26 +37,26 @@ - + - + - + @@ -66,49 +66,49 @@ - + - + - + - + - + - + - + - + - + - + - + - + - diff --git a/Open-ILS/src/Android/core/res/layout/simple_underlines.xml b/Open-ILS/src/Android/core/res/layout/simple_underlines.xml index 6cefa4a780..bcad2dc5e8 100644 --- a/Open-ILS/src/Android/core/res/layout/simple_underlines.xml +++ b/Open-ILS/src/Android/core/res/layout/simple_underlines.xml @@ -33,7 +33,7 @@ android:layout_marginLeft="4dip" android:layout_marginRight="4dip" /> - than now @returns: Array of non-catalogen circ IDs, event or error */ - public static String METHOD_FETCH_NON_CAT_CIRCS = "open-ils.circ.open_non_cataloged_circulation.user"; - - /** The METHOD_FETCH_CIRC_BY_ID description : Retrieves a circ object by ID. @returns : "circ" class. Fields of interest : renewal_remaining, due_date */ - public static String METHOD_FETCH_CIRC_BY_ID = "open-ils.circ.retrieve"; - - /** The METHOD_FETCH_MODS_FROM_COPY description : used to return info. @returns : mvr class OSRF Object. Fields of interest : title, author */ - public static String METHOD_FETCH_MODS_FROM_COPY = "open-ils.search.biblio.mods_from_copy"; - - /** The METHOD_FETCH_COPY description : used to return info for a PRE_CATALOGED object. @returns : acp class OSRF Object. Fields of interest : dummy_title, dummy_author */ - public static String METHOD_FETCH_COPY = "open-ils.search.asset.copy.retrieve"; - - /** The METHOD_RENEW_CIRC description : used to renew a circulation object. @returnes : acn, acp, circ, mus, mbts */ - public static String METHOD_RENEW_CIRC = "open-ils.circ.renew"; - - // Used for Holds Tab - - /** The METHOD_FETCH_HOLDS. @returns: List of "ahr" OSPFObject . Fields of interest : pickup_lib */ - public static String METHOD_FETCH_HOLDS = "open-ils.circ.holds.retrieve"; - - /** The METHOD_FETCH_ORG_SETTINGS description : retrieves a setting from the organization unit. @returns : returns the requested value of the setting */ - public static String METHOD_FETCH_ORG_SETTINGS = "open-ils.actor.ou_setting.ancestor_default"; - - /** The METHOD_FETCH_MRMODS. */ - // if holdtype == M return mvr OSRFObject - public static String METHOD_FETCH_MRMODS = "open-ils.search.biblio.metarecord.mods_slim.retrieve"; - // if holdtype == T return mvr OSRFObject - /** The METHO d_ fetc h_ rmods. */ - public static String METHOD_FETCH_RMODS = "open-ils.search.biblio.record.mods_slim.retrieve"; - // if hold type V - /** The METHO d_ fetc h_ volume. */ - public static String METHOD_FETCH_VOLUME = "open-ils.search.asset.call_number.retrieve"; - // if hold type I - /** The METHO d_ fetc h_ issuance. */ - public static String METHOD_FETCH_ISSUANCE = "open-ils.serial.issuance.pub_fleshed.batch.retrieve"; - - /** The METHO d_ fetc h_ hol d_ status. */ - public static String METHOD_FETCH_HOLD_STATUS = "open-ils.circ.hold.queue_stats.retrieve"; - - /** The METHOD_UPDATE_HOLD description : Updates the specified hold. If session user != hold user then session user must have UPDATE_HOLD permissions @returns : hold_is on success, event or error on failure */ - public static String METHOD_UPDATE_HOLD = "open-ils.circ.hold.update"; - - /** The METHOD_CANCEL_HOLD description : Cancels the specified hold. session user != hold user must have CANCEL_HOLD permissions. @returns : 1 on success, event or error on failure */ - public static String METHOD_CANCEL_HOLD = "open-ils.circ.hold.cancel"; - - /** The METHOD_VERIFY_HOLD_POSSIBLE description :. @returns : hashmap with "success" : 1 field or */ - public static String METHOD_VERIFY_HOLD_POSSIBLE = "open-ils.circ.title_hold.is_possible"; - - /** The METHOD_CREATE_HOLD description :. @returns : hash with messages : "success" : 1 field or */ - public static String METHOD_CREATE_HOLD = "open-ils.circ.holds.create"; - - // Used for Fines - - /** The METHODS_FETCH_FINES_SUMMARY description :. @returns: "mous" OSRFObject. fields: balance_owed, total_owed, total_paid */ - public static String METHOD_FETCH_FINES_SUMMARY = "open-ils.actor.user.fines.summary"; - - /** The METHOD_FETCH_TRANSACTIONS description: For a given user retrieves a list of fleshed transactions. List of objects, each object is a hash containing : transaction, circ, record @returns : array of objects, must investigate */ - public static String METHOD_FETCH_TRANSACTIONS = "open-ils.actor.user.transactions.have_charge.fleshed"; - - /** The METHOD_FETCH_MONEY_BILLING description :. */ - public static String METHOD_FETCH_MONEY_BILLING = "open-ils.circ.money.billing.retrieve.all"; - - // Used for book bags - /** The METHOD_FLESH_CONTAINERS description : Retrieves all un-fleshed buckets by class assigned to a given user VIEW_CONTAINER permissions is requestID != owner ID. @returns : array of "cbreb" OSRFObjects */ - public static String METHOD_FLESH_CONTAINERS = "open-ils.actor.container.retrieve_by_class.authoritative"; - - /** The METHOD_FLESH_PUBLIC_CONTAINER description : array of contaoners correspondig to a id. @returns : array of "crebi" OSRF objects (content of bookbag, id's of elements to get more info) */ - public static String METHOD_FLESH_PUBLIC_CONTAINER = "open-ils.actor.container.flesh"; - - /** The METHO d_ containe r_ delete. */ - public static String METHOD_CONTAINER_DELETE = "open-ils.actor.container.item.delete"; - - /** The METHO d_ containe r_ create. */ - public static String METHOD_CONTAINER_CREATE = "open-ils.actor.container.create"; - - /** The METHO d_ containe r_ ite m_ create. */ - public static String METHOD_CONTAINER_ITEM_CREATE = "open-ils.actor.container.item.create"; - - /** The METHO d_ containe r_ ful l_ delete. */ - public static String METHOD_CONTAINER_FULL_DELETE = "open-ils.actor.container.full_delete"; - - /** The book bags. */ - private ArrayList bookBags = new ArrayList(); - - /** The conn. */ - public HttpConnection conn; - - /** The http address. */ - private String httpAddress = "http://ulysses.calvin.edu"; - - /** The TAG. */ - private final String TAG = AccountAccess.class.getName(); - - /** - * The auth token. Sent with every request that needs authentication - * */ - private String authToken = null; - - /** The cm. */ - private ConnectivityManager cm = null; - - /** The auth time. */ - private Integer authTime = null; - - /** The user id. */ - private Integer userID = null; - - /** home library ID. */ - private Integer homeLibraryID = null; - - private boolean haveSession; - - /** The user name. */ - public static String userName = null; - - /** Whether we have ever established a session **/ - - /** The account access. */ - private static AccountAccess accountAccess = null; - - /** - * Instantiates a new authenticate user. - * - * @param httpAddress the http address - */ - private AccountAccess(String httpAddress) { - - Log.d(TAG, "AccountAccess ctor: " + httpAddress); - this.httpAddress = httpAddress; - - try { - // configure the connection - Log.d(TAG, "Connection with " + httpAddress); - conn = new HttpConnection(httpAddress + "/osrf-gateway-v1"); - - } catch (Exception e) { - Log.d(TAG, "Exception in establishing connection", e); - } - - } - - /** - * Gets the account access. - * - * @param httpAddress the http address - * @return the account access - */ - public static AccountAccess getAccountAccess(String httpAddress) { - - if (accountAccess == null) { - accountAccess = new AccountAccess(httpAddress); - } - if (!httpAddress.equals(accountAccess.httpAddress)) - accountAccess.updateHttpAddress(httpAddress); - - return accountAccess; - } - - // the object must be initialized before - /** - * Gets the account access. - * - * @return the account access - */ - public static AccountAccess getAccountAccess() { - return accountAccess; - } - - public Integer getHomeLibraryID() { - return homeLibraryID; - } - - public void setHomeLibraryID(Integer homeLibraryID) { - this.homeLibraryID = homeLibraryID; - } - - /* - * Change the Http conn to a new library address - */ - /** - * Update http address. - * - * @param httpAddress the http address - */ - public void updateHttpAddress(String httpAddress) { - Log.d(TAG, "update http address of account access to " - + httpAddress); - try { - // configure the connection - this.httpAddress = httpAddress; - Log.d(TAG, "Connection with " + httpAddress); - conn = new HttpConnection(httpAddress + "/osrf-gateway-v1"); - - } catch (Exception e) { - System.err.println("Exception in establishing connection " - + e.getMessage()); - } - } - - /** - * Md5. - * - * @param s - * the s - * @return the string - */ - private String md5(String s) { - try { - // Create MD5 Hash - MessageDigest digest = java.security.MessageDigest - .getInstance("MD5"); - digest.update(s.getBytes()); - byte messageDigest[] = digest.digest(); - - // Create Hex String - StringBuffer hexString = new StringBuffer(); - for (int i = 0; i < messageDigest.length; i++) { - String hex = Integer.toHexString(0xFF & messageDigest[i]); - if (hex.length() == 1) { - // could use a for loop, but we're only dealing with a - // single byte - hexString.append('0'); - } - hexString.append(hex); - } - return hexString.toString(); - - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } - - return ""; - } - - /** - * Retrieve session. - * @throws SessionNotFoundException - */ - public boolean retrieveSession(String auth_token, boolean force) throws SessionNotFoundException { - - if (!force && this.haveSession && this.authToken.equals(auth_token)) - return true; - this.haveSession = false; - this.authToken = auth_token; - - Object resp = Utils.doRequest(conn, SERVICE_AUTH, METHOD_AUTH_SESSION_RETRV, authToken, new Object[] {authToken}); - if (resp != null) { - OSRFObject au = (OSRFObject) resp; - userID = au.getInt("id"); - homeLibraryID = au.getInt("home_ou"); - userName = au.getString("usrname"); - //email = au.getString("email"); - this.haveSession = true; - } - return this.haveSession; - } - - public static boolean runningOnUIThread() { - return (Looper.myLooper() == Looper.getMainLooper()); - } - - /** invalidate current auth token and get a new one - * - * @param activity - * @return true if auth successful - */ - public boolean reauthenticate(Activity activity) throws SessionNotFoundException, AuthenticatorException, OperationCanceledException, IOException { - boolean ok = false; - final AccountManager am = AccountManager.get(activity); - final String accountType = activity.getString(R.string.ou_account_type); - final Account account = new Account(userName, accountType); - am.invalidateAuthToken(accountType, authToken); - haveSession = false; - authToken = null; - if (runningOnUIThread()) - return false; - Bundle b = am.getAuthToken(account, Const.AUTHTOKEN_TYPE, null, activity, null, null).getResult(); - final String new_authToken = b.getString(AccountManager.KEY_AUTHTOKEN); - if (TextUtils.isEmpty(new_authToken)) - return false; - return retrieveSession(new_authToken, true); - } - - // ------------------------Checked Out Items Section - // -------------------------// - - /** - * Gets the items checked out. - * - * @return the items checked out - * @throws SessionNotFoundException the session not found exception - */ - public ArrayList getItemsCheckedOut() - throws SessionNotFoundException { - - ArrayList circRecords = new ArrayList(); - - Object resp = Utils.doRequest(conn, SERVICE_ACTOR, - METHOD_FETCH_CHECKED_OUT_SUM, authToken, new Object[] { - authToken, userID }); - if (resp == null) - return circRecords; - Map resp_map = ((Map) resp); - - if (resp_map.get("out") != null) { - List out_id = (List) resp_map.get("out"); - for (int i = 0; i < out_id.size(); i++) { - OSRFObject circ = retrieveCircRecord(out_id.get(i)); - CircRecord circRecord = new CircRecord(circ, CircRecord.OUT, - Integer.parseInt(out_id.get(i))); - fetchInfoForCheckedOutItem(circ.getInt("target_copy"), circRecord); - circRecords.add(circRecord); - } - } - - if (resp_map.get("overdue") != null) { - List overdue_id = (List) resp_map.get("overdue"); - for (int i = 0; i < overdue_id.size(); i++) { - OSRFObject circ = retrieveCircRecord(overdue_id.get(i)); - CircRecord circRecord = new CircRecord(circ, CircRecord.OVERDUE, - Integer.parseInt(overdue_id.get(i))); - fetchInfoForCheckedOutItem(circ.getInt("target_copy"), circRecord); - circRecords.add(circRecord); - } - } - - /* Other fields returned by the request; apparently not used in OPAC - resp_map.get("claims_returned"); - resp_map.get("long_overdue") - resp_map.get("lost"); - */ - - Collections.sort(circRecords, new Comparator() { - @Override - public int compare(CircRecord lhs, CircRecord rhs) { - return lhs.getDueDate().compareTo(rhs.getDueDate()); - } - }); - - return circRecords; - } - - /* - * Retrieves the Circ record - * - * @param : target_copy from circ - * - * @returns : "circ" OSRFObject - */ - /** - * Retrieve circ record. - * - * @param id the id - * @return the oSRF object - * @throws SessionNotFoundException the session not found exception - */ - private OSRFObject retrieveCircRecord(String id) - throws SessionNotFoundException { - - OSRFObject circ = (OSRFObject) Utils.doRequest(conn, SERVICE_CIRC, - METHOD_FETCH_CIRC_BY_ID, authToken, new Object[] { - authToken, id }); - return circ; - } - - /* - * Fetch info for Checked Out Items It uses two methods : - * open-ils.search.biblio.mods_from_copy or in case of pre-cataloged records - * it uses open-ils.search.asset.copy.retriev Usefull info : title and - * author (for acp : dummy_title, dummy_author) - */ - /** - * Fetch info for checked out item. - * - * @param target_copy the target_copy - * @param circRecord the circ record - * @return the oSRF object - */ - private OSRFObject fetchInfoForCheckedOutItem(Integer target_copy, - CircRecord circRecord) { - - if (target_copy == null) - return null; - - OSRFObject result; - Log.d(TAG, "Mods from copy"); - OSRFObject info_mvr = fetchModsFromCopy(target_copy); - // if title or author not inserted, request acp with copy_target - result = info_mvr; - OSRFObject info_acp = null; - - // the logic to establish mvr or acp is copied from the opac - if (info_mvr.getString("title") == null - || info_mvr.getString("author") == null) { - Log.d(TAG, "Asset"); - info_acp = fetchAssetCopy(target_copy); - result = info_acp; - circRecord.acp = info_acp; - circRecord.circ_info_type = CircRecord.ACP_OBJ_TYPE; - } else { - circRecord.mvr = info_mvr; - circRecord.circ_info_type = CircRecord.MVR_OBJ_TYPE; - } - return result; - } - - /** - * Fetch mods from copy. - * - * @param target_copy the target_copy - * @return the oSRF object - */ - private OSRFObject fetchModsFromCopy(Integer target_copy) { - - // sync request - OSRFObject mvr = (OSRFObject) Utils.doRequest(conn, SERVICE_SEARCH, - METHOD_FETCH_MODS_FROM_COPY, cm, new Object[] { target_copy }); - - return mvr; - } - - /** - * Fetch asset copy. - * - * @param target_copy the target_copy - * @return the oSRF object - */ - private OSRFObject fetchAssetCopy(Integer target_copy) { - - OSRFObject acp = (OSRFObject) Utils.doRequest(conn, SERVICE_SEARCH, - METHOD_FETCH_COPY, cm, new Object[] { target_copy }); - - return acp; - } - - /* - * Method used to renew a circulation record based on target_copy_id Returns - * many objects, don't think they are needed - */ - /** - * Renew circ. - * - * @param target_copy the target_copy - * @throws MaxRenewalsException the max renewals exception - * @throws ServerErrorMessage the server error message - * @throws SessionNotFoundException the session not found exception - */ - public void renewCirc(Integer target_copy) throws MaxRenewalsException, - ServerErrorMessage, SessionNotFoundException { - - HashMap complexParam = new HashMap(); - complexParam.put("patron", this.userID); - complexParam.put("copyid", target_copy); - complexParam.put("opac_renewal", 1); - - Object a_lot = (Object) Utils.doRequest(conn, SERVICE_CIRC, - METHOD_RENEW_CIRC, authToken, new Object[] { authToken, - complexParam }); - - Map resp = (Map) a_lot; - - if (resp.get("textcode") != null && !resp.get("textcode").equals("SUCCESS")) { - if (resp.get("textcode").equals("MAX_RENEWALS_REACHED")) - throw new MaxRenewalsException(); - throw new ServerErrorMessage(resp.get("desc").toString()); - } - - } - - // ------------------------Holds Section - // --------------------------------------// - - /** - * Fetch org settings. - * - * @param org_id the org_id - * @param setting the setting - * @return the object - * @throws SessionNotFoundException the session not found exception - */ - public Object fetchOrgSettings(Integer org_id, String setting) - throws SessionNotFoundException { - - OSRFObject response = (OSRFObject) Utils - .doRequest(conn, SERVICE_ACTOR, METHOD_FETCH_ORG_SETTINGS, cm, - new Object[] { org_id, setting }); - return response; - - } - - /** - * Gets the holds. - * - * @return the holds - * @throws SessionNotFoundException the session not found exception - */ - public List getHolds() throws SessionNotFoundException { - - ArrayList holds = new ArrayList(); - - // fields of interest : expire_time - List listHoldsAhr = null; - - Object resp = Utils.doRequest(conn, SERVICE_CIRC, METHOD_FETCH_HOLDS, - authToken, new Object[] { authToken, userID }); - if (resp == null) { - Log.d(TAG, "Result: null"); - return holds; - } - - listHoldsAhr = (List) resp; - - for (int i = 0; i < listHoldsAhr.size(); i++) { - // create hold item - HoldRecord hold = new HoldRecord(listHoldsAhr.get(i)); - // get title - fetchHoldTitleInfo(listHoldsAhr.get(i), hold); - - // get status - fetchHoldStatus(listHoldsAhr.get(i), hold); - - holds.add(hold); - } - return holds; - } - - /* - * hold target type : M - metarecord T - record V - volume I - issuance C - - * copy P - pat - */ - - /** - * Fetch hold title info. - * - * @param holdArhObject the hold arh object - * @param hold the hold - * @return the object - */ - private Object fetchHoldTitleInfo(OSRFObject holdArhObject, HoldRecord hold) { - - String holdType = (String) holdArhObject.get("hold_type"); - - String method = null; - - Object response; - OSRFObject holdInfo = null; - if (holdType.equals("T") || holdType.equals("M")) { - - if (holdType.equals("M")) - method = METHOD_FETCH_MRMODS; - if (holdType.equals("T")) - method = METHOD_FETCH_RMODS; - holdInfo = (OSRFObject) Utils.doRequest(conn, SERVICE_SEARCH, - method, cm, new Object[] { holdArhObject.get("target") }); - - // Log.d(TAG, "Hold here " + holdInfo); - hold.title = ((OSRFObject) holdInfo).getString("title"); - hold.author = ((OSRFObject) holdInfo).getString("author"); - hold.recordInfo = new RecordInfo((OSRFObject) holdInfo); - try { - hold.types_of_resource = ((List) holdInfo - .get("types_of_resource")).get(0).toString(); - } catch (Exception e) { - System.err.println("Can't get types of resurce type" - + e.getMessage()); - } - ; - } else { - // multiple objects per hold ???? - holdInfo = holdFetchObjects(holdArhObject, hold); - - } - return holdInfo; - } - - /** - * Hold fetch objects. - * - * @param hold the hold - * @param holdObj the hold obj - * @return the oSRF object - */ - private OSRFObject holdFetchObjects(OSRFObject hold, HoldRecord holdObj) { - - String type = (String) hold.get("hold_type"); - - Log.d(TAG, "Hold Type " + type); - if (type.equals("C")) { - - /* - * steps asset.copy'->'asset.call_number'->'biblio.record_entry' or, - * in IDL ids, acp->acn->bre - */ - - // fetch_copy - OSRFObject copyObject = fetchAssetCopy(hold.getInt("target")); - // fetch_volume from copyObject.call_number field - Integer call_number = copyObject.getInt("call_number"); - - if (call_number != null) { - - OSRFObject volume = (OSRFObject) Utils.doRequest(conn, - SERVICE_SEARCH, METHOD_FETCH_VOLUME, cm, - new Object[] { copyObject.getInt("call_number") }); - // in volume object : record - Integer record = volume.getInt("record"); - - // part label - holdObj.part_label = volume.getString("label"); - - Log.d(TAG, "Record " + record); - OSRFObject holdInfo = (OSRFObject) Utils.doRequest(conn, - SERVICE_SEARCH, METHOD_FETCH_RMODS, cm, - new Object[] { record }); - - holdObj.title = holdInfo.getString("title"); - holdObj.author = holdInfo.getString("author"); - holdObj.recordInfo = new RecordInfo((OSRFObject) holdInfo); - try { - holdObj.types_of_resource = ((List) holdInfo - .get("types_of_resource")).get(0).toString(); - } catch (Exception e) { - System.err.println("Can't get types of resurce type" - + e.getMessage()); - } - } - - return copyObject; - } else if (type.equals("V")) { - // must test - - // fetch_volume - OSRFObject volume = (OSRFObject) Utils.doRequest(conn, - SERVICE_SEARCH, METHOD_FETCH_VOLUME, cm, - new Object[] { hold.getInt("target") }); - // in volume object : record - - // in volume object : record - Integer record = volume.getInt("record"); - - // part label - holdObj.part_label = volume.getString("label"); - - Log.d(TAG, "Record " + record); - OSRFObject holdInfo = (OSRFObject) Utils.doRequest(conn, - SERVICE_SEARCH, METHOD_FETCH_RMODS, cm, - new Object[] { record }); - - holdObj.title = holdInfo.getString("title"); - holdObj.author = holdInfo.getString("author"); - holdObj.recordInfo = new RecordInfo((OSRFObject) holdInfo); - try { - holdObj.types_of_resource = ((List) holdInfo - .get("types_of_resource")).get(0).toString(); - } catch (Exception e) { - System.err.println("Can't get types of resurce type" - + e.getMessage()); - } - } else if (type.equals("I")) { - OSRFObject issuance = (OSRFObject) Utils.doRequest(conn, - SERVICE_SERIAL, METHOD_FETCH_ISSUANCE, cm, - new Object[] { hold.getInt("target") }); - // TODO - - } else if (type.equals("P")) { - HashMap param = new HashMap(); - - param.put("cache", 1); - - ArrayList fieldsList = new ArrayList(); - fieldsList.add("label"); - fieldsList.add("record"); - - param.put("fields", fieldsList); - HashMap queryParam = new HashMap(); - // PART_ID use "target field in hold" - queryParam.put("id", hold.getInt("target")); - param.put("query", queryParam); - - // returns [{record:id, label=part label}] - - List part = (List) Utils.doRequest(conn, - SERVICE_FIELDER, "open-ils.fielder.bmp.atomic", cm, - new Object[] { param }); - - Map partObj = (Map) part.get(0); - - Integer recordID = (Integer) partObj.get("record"); - String part_label = (String) partObj.get("label"); - - OSRFObject holdInfo = (OSRFObject) Utils.doRequest(conn, - SERVICE_SEARCH, METHOD_FETCH_RMODS, cm, - new Object[] { recordID }); - - holdObj.part_label = part_label; - holdObj.title = holdInfo.getString("title"); - holdObj.author = holdInfo.getString("author"); - holdObj.recordInfo = new RecordInfo((OSRFObject) holdInfo); - try { - holdObj.types_of_resource = ((List) holdInfo - .get("types_of_resource")).get(0).toString(); - } catch (Exception e) { - System.err.println("Can't get types of resurce type" - + e.getMessage()); - } - } - - return null; - } - - /** - * Fetch hold status. - * - * @param hold the hold - * @param holdObj the hold obj - * @throws SessionNotFoundException the session not found exception - */ - public void fetchHoldStatus(OSRFObject hold, HoldRecord holdObj) - throws SessionNotFoundException { - - Integer hold_id = hold.getInt("id"); - // MAP : potential_copies, status, total_holds, queue_position, - // estimated_wait - Object resp = Utils.doRequest(conn, SERVICE_CIRC, - METHOD_FETCH_HOLD_STATUS, authToken, new Object[] { - authToken, hold_id }); - - Map map = (Map)resp; - holdObj.status = map.get("status"); - holdObj.potentialCopies = map.get("potential_copies"); - holdObj.estimatedWaitInSeconds = map.get("estimated_wait"); - holdObj.queuePosition = map.get("queue_position"); - holdObj.totalHolds = map.get("total_holds"); - } - - /** - * Cancel hold. - * - * @param hold the hold - * @return true, if successful - * @throws SessionNotFoundException the session not found exception - */ - public boolean cancelHold(OSRFObject hold) throws SessionNotFoundException { - - Integer hold_id = hold.getInt("id"); - - Object response = Utils.doRequest(conn, SERVICE_CIRC, - METHOD_CANCEL_HOLD, authToken, new Object[] { authToken, - hold_id }); - - // delete successful - if (response.toString().equals("1")) - return true; - - return false; - - } - - /** - * Update hold. - * - * @param ahr the ahr - * @param pickup_lib the pickup_lib - * @param suspendHold the suspend hold - * @param expire_time the expire_time - * @param thaw_date the thaw_date - * @return the object - * @throws SessionNotFoundException the session not found exception - */ - public Object updateHold(OSRFObject ahr, Integer pickup_lib, - boolean suspendHold, String expire_time, String thaw_date) - throws SessionNotFoundException { - // TODO verify that object is correct passed to the server - - ahr.put("pickup_lib", pickup_lib); - ahr.put("expire_time", expire_time); - // frozen set, what this means ? - ahr.put("frozen", suspendHold); - // only if it is frozen - ahr.put("thaw_date", thaw_date); - - Object response = Utils.doRequest(conn, SERVICE_CIRC, - METHOD_UPDATE_HOLD, authToken, new Object[] { authToken, - ahr }); - - return response; - } - - /** - * Creates the hold. - * - * @param recordID the record id - * @param pickup_lib the pickup_lib - * @param email_notify the email_notify - * @param phone_notify the phone_notify - * @param phone the phone - * @param suspendHold the suspend hold - * @param expire_time the expire_time - * @param thaw_date the thaw_date - * @return the string[] - * @throws SessionNotFoundException the session not found exception - */ - public String[] createHold(Integer recordID, Integer pickup_lib, - boolean email_notify, boolean phone_notify, String phone, - boolean suspendHold, String expire_time, String thaw_date) - throws SessionNotFoundException { - - OSRFObject ahr = new OSRFObject("ahr"); - ahr.put("target", recordID); - ahr.put("usr", userID); - ahr.put("requestor", userID); - - // TODO - // only gold type 'T' for now - ahr.put("hold_type", "T"); - ahr.put("pickup_lib", pickup_lib); // pick-up lib - ahr.put("phone_notify", phone); - ahr.put("email_notify", email_notify); - ahr.put("expire_time", expire_time); - // frozen set, what this means ? - ahr.put("frozen", suspendHold); - // only if it is frozen - ahr.put("thaw_date", thaw_date); - - // extra parameters (not mandatory for hold creation) - - Object response = Utils.doRequest(conn, SERVICE_CIRC, - METHOD_CREATE_HOLD, authToken, new Object[] { authToken, - ahr }); - - String[] resp = new String[3]; - // if we can get hold ID then we return true - try { - - Integer id = Integer.parseInt(response.toString()); - if (id > -1) - resp[0] = "true"; - - } catch (Exception e) { - - List respErrorMessage = (List) response; - - Object map = respErrorMessage.get(0); - resp[0] = "false"; - - resp[1] = ((Map) map).get("textcode"); - resp[2] = ((Map) map).get("desc"); - } - - Log.d(TAG, "Result " + resp[1] + " " + resp[2]); - - // else we return false - return resp; - } - - // ?? return boolean - /** - * Checks if is hold possible. - * - * @param pickup_lib the pickup_lib - * @param recordID the record id - * @return the object - * @throws SessionNotFoundException the session not found exception - */ - public Object isHoldPossible(Integer pickup_lib, Integer recordID) - throws SessionNotFoundException { - - HashMap mapAsk = getHoldPreCreateInfo(recordID, - pickup_lib); - mapAsk.put("pickup_lib", pickup_lib); - mapAsk.put("hold_type", null); - mapAsk.put("patronid", userID); - mapAsk.put("volume_id", null); - mapAsk.put("issuanceid", null); - mapAsk.put("copy_id", null); - mapAsk.put("depth", 0); - mapAsk.put("part_id", null); - mapAsk.put("holdable_formats", null); - // {"titleid":63,"mrid":60,"volume_id":null,"issuanceid":null,"copy_id":null,"hold_type":"T","holdable_formats":null, - // "patronid":2,"depth":0,"pickup_lib":"8","partid":null} - - Object response = Utils.doRequest(conn, SERVICE_CIRC, - METHOD_VERIFY_HOLD_POSSIBLE, authToken, new Object[] { - authToken, mapAsk }); - - return response; - } - - // return - /** - * Gets the hold pre create info. - * - * @param recordID the record id - * @param pickup_lib the pickup_lib - * @return the hold pre create info - */ - public HashMap getHoldPreCreateInfo(Integer recordID, - Integer pickup_lib) { - - HashMap param = new HashMap(); - - param.put("pickup_lib", pickup_lib); - param.put("record", recordID); - - Map response = (Map) Utils.doRequest(conn, - SERVICE_SEARCH, - "open-ils.search.metabib.record_to_descriptors", cm, - new Object[] { param }); - - Object obj = response.get("metarecord"); - Log.d(TAG, "metarecord="+obj); - Integer metarecordID = Integer.parseInt(obj.toString()); - - HashMap map = new HashMap(); - map.put("titleid", recordID); - map.put("mrid", metarecordID); - - return map; - /* - * Methods to get necessary info on hold - * open-ils.search.metabib.record_to_descriptors - * - * open-ils.search.biblio.record_hold_parts - */ - } - - // ----------------------------Fines - // Summary------------------------------------// - - /** - * Gets the fines summary. - * - * @return the fines summary - * @throws SessionNotFoundException the session not found exception - */ - public float[] getFinesSummary() throws SessionNotFoundException { - - // mous object - OSRFObject finesSummary = (OSRFObject) Utils.doRequest(conn, - SERVICE_ACTOR, METHOD_FETCH_FINES_SUMMARY, authToken, - new Object[] { authToken, userID }); - - float fines[] = new float[3]; - try { - fines[0] = Float.parseFloat(finesSummary.getString("total_owed")); - fines[1] = Float.parseFloat(finesSummary.getString("total_paid")); - fines[2] = Float.parseFloat(finesSummary.getString("balance_owed")); - } catch (Exception e) { - System.err.println("Exception in parsing fines " + e.getMessage()); - } - - return fines; - } - - /** - * Gets the transactions. - * - * @return the transactions - * @throws SessionNotFoundException the session not found exception - */ - public ArrayList getTransactions() - throws SessionNotFoundException { - - ArrayList finesRecords = new ArrayList(); - - Object transactions = Utils.doRequest(conn, SERVICE_ACTOR, - METHOD_FETCH_TRANSACTIONS, authToken, new Object[] { - authToken, userID }); - - // get Array - - List> list = (List>) transactions; - - for (int i = 0; i < list.size(); i++) { - - Map item = list.get(i); - - FinesRecord record = new FinesRecord(item.get("circ"), - item.get("record"), item.get("transaction")); - finesRecords.add(record); - } - - return finesRecords; - } - - // ---------------------------------------Book - // bags-----------------------------------// - - /** - * Retrieve bookbags from the server. - * - * @return the bookbags - * @throws SessionNotFoundException the session not found exception - */ - public boolean retrieveBookbags() throws SessionNotFoundException { - - Object response = Utils.doRequest(conn, SERVICE_ACTOR, - METHOD_FLESH_CONTAINERS, authToken, new Object[] { - authToken, userID, "biblio", "bookbag" }); - - List bookbags = (List) response; - - ArrayList bookBagObj = new ArrayList(); - // in order to refresh bookbags - this.bookBags = bookBagObj; - - if (bookbags == null) - return true; - - for (int i = 0; i < bookbags.size(); i++) { - - BookBag bag = new BookBag(bookbags.get(i)); - getBookbagContent(bag, bookbags.get(i).getInt("id")); - - bookBagObj.add(bag); - } - return true; - } - - public ArrayList getBookbags() { - return this.bookBags; - } - - /** - * Gets the bookbag content. - * - * @param bag the bag - * @param bookbagID the bookbag id - * @return the bookbag content - * @throws SessionNotFoundException the session not found exception - */ - private Object getBookbagContent(BookBag bag, Integer bookbagID) - throws SessionNotFoundException { - - Map map = (Map) Utils.doRequest(conn, - SERVICE_ACTOR, METHOD_FLESH_PUBLIC_CONTAINER, authToken, - new Object[] { authToken, "biblio", bookbagID }); - - List items = new ArrayList(); - - try{ - items = (List) map.get("items"); - - for (int i = 0; i < items.size(); i++) { - - BookBagItem bookBagItem = new BookBagItem(items.get(i)); - - bag.items.add(bookBagItem); - } - - }catch(Exception e){}; - - return items; - } - - /** - * Removes the bookbag item. - * - * @param id the id - * @throws SessionNotFoundException the session not found exception - */ - public void removeBookbagItem(Integer id) throws SessionNotFoundException { - - removeContainer("biblio", id); - - } - - /** - * Creates the bookbag. - * - * @param name the name - * @throws SessionNotFoundException the session not found exception - */ - public void createBookbag(String name) throws SessionNotFoundException { - - OSRFObject cbreb = new OSRFObject("cbreb"); - cbreb.put("btype", "bookbag"); - cbreb.put("name", name); - cbreb.put("pub", false); - cbreb.put("owner", userID); - - createContainer("biblio", cbreb); - } - - /** - * Delete book bag. - * - * @param id the id - * @throws SessionNotFoundException the session not found exception - */ - public void deleteBookBag(Integer id) throws SessionNotFoundException { - - Object response = Utils.doRequest(conn, SERVICE_ACTOR, - METHOD_CONTAINER_FULL_DELETE, authToken, new Object[] { - authToken, "biblio", id }); - } - - /** - * Adds the record to book bag. - * - * @param record_id the record_id - * @param bookbag_id the bookbag_id - * @throws SessionNotFoundException the session not found exception - */ - public void addRecordToBookBag(Integer record_id, Integer bookbag_id) - throws SessionNotFoundException { - - OSRFObject cbrebi = new OSRFObject("cbrebi"); - cbrebi.put("bucket", bookbag_id); - cbrebi.put("target_biblio_record_entry", record_id); - cbrebi.put("id", null); - - Object response = Utils.doRequest(conn, SERVICE_ACTOR, - METHOD_CONTAINER_ITEM_CREATE, authToken, new Object[] { - authToken, "biblio", cbrebi }); - } - - /** - * Removes the container. - * - * @param container the container - * @param id the id - * @throws SessionNotFoundException the session not found exception - */ - private void removeContainer(String container, Integer id) - throws SessionNotFoundException { - - Object response = Utils.doRequest(conn, SERVICE_ACTOR, - METHOD_CONTAINER_DELETE, authToken, new Object[] { - authToken, container, id }); - } - - /** - * Creates the container. - * - * @param container the container - * @param parameter the parameter - * @throws SessionNotFoundException the session not found exception - */ - private void createContainer(String container, Object parameter) - throws SessionNotFoundException { - - Object response = Utils.doRequest(conn, SERVICE_ACTOR, - METHOD_CONTAINER_CREATE, authToken, new Object[] { - authToken, container, parameter }); - } -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/MaxRenewalsException.java b/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/MaxRenewalsException.java deleted file mode 100644 index e92e57ddd6..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/MaxRenewalsException.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.accountAccess; - -public class MaxRenewalsException extends Exception { - - /** - * - */ - private static final long serialVersionUID = 1L; - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/ServerErrorMessage.java b/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/ServerErrorMessage.java deleted file mode 100644 index 2e8ee4db2e..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/ServerErrorMessage.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.accountAccess; - -public class ServerErrorMessage extends Exception { - - /** - * - */ - private static final long serialVersionUID = 3341617529835568018L; - - public String message; - - public ServerErrorMessage(String message) { - this.message = message; - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/SessionNotFoundException.java b/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/SessionNotFoundException.java deleted file mode 100644 index 130dbb7f50..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/SessionNotFoundException.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.accountAccess; - -public class SessionNotFoundException extends Exception { - - /** - * - */ - private static final long serialVersionUID = 123232L; - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/bookbags/BookBag.java b/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/bookbags/BookBag.java deleted file mode 100644 index f3b84c04b8..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/bookbags/BookBag.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.accountAccess.bookbags; - -import java.io.Serializable; -import java.util.ArrayList; - -import org.opensrf.util.OSRFObject; - -public class BookBag implements Serializable { - - public int id; - - public String name = null; - - public String description = null; - - public Boolean shared = null; - - public ArrayList items = null; - - public BookBag(OSRFObject object) { - - this.id = object.getInt("id"); - this.name = object.getString("name"); - this.description = object.getString("description"); - this.items = new ArrayList(); - - String pub_visible = object.getString("pub"); - - if (pub_visible.equals("f")) - this.shared = false; - else - this.shared = true; - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/bookbags/BookBagDetails.java b/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/bookbags/BookBagDetails.java deleted file mode 100644 index ca50395308..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/bookbags/BookBagDetails.java +++ /dev/null @@ -1,361 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.accountAccess.bookbags; - -import java.util.ArrayList; -import java.util.List; - -import org.evergreen.android.R; -import org.evergreen.android.accountAccess.AccountAccess; -import org.evergreen.android.accountAccess.SessionNotFoundException; -import org.evergreen.android.searchCatalog.RecordInfo; -import org.evergreen.android.searchCatalog.SearchCatalog; -import org.evergreen.android.searchCatalog.SearchCatalogListView; -import org.evergreen.android.views.AccountScreenDashboard; -import org.evergreen.android.views.splashscreen.SplashActivity; - -import android.app.Activity; -import android.app.AlertDialog; -import android.app.AlertDialog.Builder; -import android.app.ProgressDialog; -import android.app.Service; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.net.ConnectivityManager; -import android.os.Bundle; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemSelectedListener; -import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.ListView; -import android.widget.TextView; -import android.widget.Toast; - -public class BookBagDetails extends Activity { - - private final String TAG = BookBagDetails.class.getName(); - - public static final int RESULT_CODE_UPDATE = 1; - - private SearchCatalog search; - - private AccountAccess accountAccess; - - private ListView lv; - - private BookBagItemsArrayAdapter listAdapter = null; - - private ArrayList bookBagItems = null; - - private Context context; - - private ProgressDialog progressDialog; - - private BookBag bookBag; - - private TextView bookbag_name; - - private Button delete_bookbag_button; - - private Button homeButton; - - private Button myAccountButton; - - private TextView headerTitle; - - private Runnable getBookBagsItemsRunnable; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (!SplashActivity.isAppInitialized()) { - SplashActivity.restartApp(this); - return; - } - - setContentView(R.layout.bookbagitem_list); - // header portion actions - homeButton = (Button) findViewById(R.id.action_bar_home_button); - myAccountButton = (Button) findViewById(R.id.my_account_button); - - myAccountButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(getApplicationContext(), - AccountScreenDashboard.class); - startActivity(intent); - } - }); - - homeButton.setText(R.string.bookbag_details_title); - homeButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(getApplicationContext(), - SearchCatalogListView.class); - startActivity(intent); - } - }); - // end header portion actions - - accountAccess = AccountAccess.getAccountAccess(); - bookBag = (BookBag) getIntent().getSerializableExtra("bookBag"); - - context = this; - search = SearchCatalog - .getInstance((ConnectivityManager) getSystemService(Service.CONNECTIVITY_SERVICE)); - bookbag_name = (TextView) findViewById(R.id.bookbag_name); - delete_bookbag_button = (Button) findViewById(R.id.remove_bookbag); - bookbag_name.setText(bookBag.name); - delete_bookbag_button.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - - final Thread deleteBookbag = new Thread(new Runnable() { - - @Override - public void run() { - - try { - accountAccess.deleteBookBag(bookBag.id); - } catch (SessionNotFoundException e) { - e.printStackTrace(); - } - runOnUiThread(new Runnable() { - @Override - public void run() { - progressDialog.dismiss(); - setResult(RESULT_CODE_UPDATE); - finish(); - } - }); - } - }); - - Builder confirmationDialogBuilder = new AlertDialog.Builder( - context); - confirmationDialogBuilder.setMessage("Delete bookbag?"); - - confirmationDialogBuilder.setNegativeButton( - android.R.string.no, null); - confirmationDialogBuilder.setPositiveButton( - android.R.string.yes, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, - int which) { - - progressDialog = ProgressDialog.show(context, - getResources().getText(R.string.dialog_please_wait), - "Deleting Bookbag"); - deleteBookbag.start(); - } - }); - - confirmationDialogBuilder.create().show(); - - } - }); - - lv = (ListView) findViewById(R.id.bookbagitem_list); - bookBagItems = new ArrayList(); - listAdapter = new BookBagItemsArrayAdapter(context, - R.layout.bookbagitem_list_item, bookBagItems); - lv.setAdapter(listAdapter); - - lv.setOnItemSelectedListener(new OnItemSelectedListener() { - - @Override - public void onItemSelected(AdapterView arg0, View arg1, - int arg2, long arg3) { - - } - - @Override - public void onNothingSelected(AdapterView arg0) { - // TODO Auto-generated method stub - - } - - }); - - getBookBagsItemsRunnable = new Runnable() { - - @Override - public void run() { - - ArrayList records = new ArrayList(); - ArrayList ids = new ArrayList(); - - for (int i = 0; i < bookBag.items.size(); i++) { - ids.add(bookBag.items.get(i).target_copy); - } - records = search.getRecordsInfo(ids); - - for (int i = 0; i < bookBag.items.size(); i++) { - bookBag.items.get(i).recordInfo = records.get(i); - } - - runOnUiThread(new Runnable() { - - @Override - public void run() { - - listAdapter.clear(); - - for (int i = 0; i < bookBag.items.size(); i++) - listAdapter.add(bookBag.items.get(i)); - - progressDialog.dismiss(); - - if (bookBagItems.size() == 0) - Toast.makeText(context, "No circ records", - Toast.LENGTH_LONG); - - listAdapter.notifyDataSetChanged(); - } - }); - - } - }; - - Thread getBookBags = new Thread(getBookBagsItemsRunnable); - - progressDialog = ProgressDialog.show(context, - getResources().getText(R.string.dialog_please_wait), - "Retrieving bookbag data"); - getBookBags.start(); - - } - - class BookBagItemsArrayAdapter extends ArrayAdapter { - private static final String tag = "BookbagArrayAdapter"; - - private TextView title; - private TextView author; - private Button remove; - - private List records = new ArrayList(); - - public BookBagItemsArrayAdapter(Context context, - int textViewResourceId, List objects) { - super(context, textViewResourceId, objects); - this.records = objects; - } - - public int getCount() { - return this.records.size(); - } - - public BookBagItem getItem(int index) { - return this.records.get(index); - } - - public View getView(int position, View convertView, ViewGroup parent) { - View row = convertView; - - // Get item - final BookBagItem record = getItem(position); - - // if it is the right type of view - if (row == null) { - - Log.d(tag, "Starting XML Row Inflation ... "); - LayoutInflater inflater = (LayoutInflater) this.getContext() - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - row = inflater.inflate(R.layout.bookbagitem_list_item, parent, - false); - Log.d(tag, "Successfully completed XML Row Inflation!"); - - } - - title = (TextView) row.findViewById(R.id.bookbagitem_title); - - author = (TextView) row.findViewById(R.id.bookbagitem_author); - - remove = (Button) row.findViewById(R.id.bookbagitem_remove_button); - - title.setText(record.recordInfo.title); - - author.setText(record.recordInfo.author); - - remove.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - - Thread removeItem = new Thread(new Runnable() { - - @Override - public void run() { - - runOnUiThread(new Runnable() { - @Override - public void run() { - progressDialog = ProgressDialog.show(context, - getResources().getText(R.string.dialog_please_wait), - "Removing item"); - } - }); - - try { - accountAccess.removeBookbagItem(record.id); - } catch (SessionNotFoundException e) { - try { - if (accountAccess.reauthenticate(BookBagDetails.this)) - accountAccess.removeBookbagItem(record.id); - } catch (Exception e1) { - } - } - - runOnUiThread(new Runnable() { - @Override - public void run() { - progressDialog.dismiss(); - - Thread getBookBags = new Thread( - getBookBagsItemsRunnable); - setResult(RESULT_CODE_UPDATE); - - bookBag.items.remove(record); - progressDialog = ProgressDialog.show(context, - getResources().getText(R.string.dialog_please_wait), - "Retrieving bookbag data"); - getBookBags.start(); - - } - }); - } - }); - - removeItem.start(); - } - }); - - return row; - } - } -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/bookbags/BookBagItem.java b/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/bookbags/BookBagItem.java deleted file mode 100644 index 579a5d9ca8..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/bookbags/BookBagItem.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.accountAccess.bookbags; - -import java.io.Serializable; - -import org.evergreen.android.searchCatalog.RecordInfo; -import org.opensrf.util.OSRFObject; - -public class BookBagItem implements Serializable { - - public int target_copy; - - public int id; - - public RecordInfo recordInfo; - - public BookBagItem(OSRFObject cbrebi) { - - this.target_copy = cbrebi.getInt("target_biblio_record_entry"); - this.id = cbrebi.getInt("id"); - - } -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/bookbags/BookbagsListView.java b/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/bookbags/BookbagsListView.java deleted file mode 100644 index 2aafa378bc..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/bookbags/BookbagsListView.java +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.accountAccess.bookbags; - -import java.util.ArrayList; -import java.util.List; - -import org.evergreen.android.R; -import org.evergreen.android.accountAccess.AccountAccess; -import org.evergreen.android.accountAccess.SessionNotFoundException; -import org.evergreen.android.searchCatalog.SearchCatalogListView; -import org.evergreen.android.views.AccountScreenDashboard; -import org.evergreen.android.views.splashscreen.SplashActivity; - -import android.app.Activity; -import android.app.ProgressDialog; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemSelectedListener; -import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.CheckBox; -import android.widget.EditText; -import android.widget.ListView; -import android.widget.TextView; -import android.widget.Toast; - -public class BookbagsListView extends Activity { - - private final String TAG = BookbagsListView.class.getName(); - - private AccountAccess accountAccess = null; - - private ListView lv; - - private BookBagsArrayAdapter listAdapter = null; - - private ArrayList bookBags = null; - - private Context context; - - private ProgressDialog progressDialog; - - private EditText bookbag_name; - - private Button create_bookbag; - - private Runnable getBookbagsRunnable; - - private Button homeButton; - - private Button myAccountButton; - - private TextView headerTitle; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (!SplashActivity.isAppInitialized()) { - SplashActivity.restartApp(this); - return; - } - - setContentView(R.layout.bookbag_list); - - // header portion actions - myAccountButton = (Button) findViewById(R.id.my_account_button); - myAccountButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(getApplicationContext(), - AccountScreenDashboard.class); - startActivity(intent); - } - }); - - homeButton = (Button) findViewById(R.id.action_bar_home_button); - homeButton.setText(R.string.bookbag_items_title); - homeButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(getApplicationContext(), - SearchCatalogListView.class); - startActivity(intent); - } - }); - // end header portion actions - - context = this; - accountAccess = AccountAccess.getAccountAccess(); - - bookbag_name = (EditText) findViewById(R.id.bookbag_create_name); - create_bookbag = (Button) findViewById(R.id.bookbag_create_button); - lv = (ListView) findViewById(R.id.bookbag_list); - bookBags = new ArrayList(); - listAdapter = new BookBagsArrayAdapter(context, - R.layout.bookbag_list_item, bookBags); - lv.setAdapter(listAdapter); - - lv.setOnItemSelectedListener(new OnItemSelectedListener() { - - @Override - public void onItemSelected(AdapterView arg0, View arg1, - int position, long arg3) { - - Toast.makeText(getApplicationContext(), "Text", - Toast.LENGTH_LONG).show(); - } - - @Override - public void onNothingSelected(AdapterView arg0) { - // TODO Auto-generated method stub - - } - - }); - create_bookbag.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - - final String name = bookbag_name.getText().toString(); - - Thread createBookbag = new Thread(new Runnable() { - @Override - public void run() { - if (name.length() > 1) { - try { - accountAccess.createBookbag(name); - } catch (SessionNotFoundException e) { - try { - if (accountAccess.reauthenticate(BookbagsListView.this)) - accountAccess.createBookbag(name); - } catch (Exception eauth) { - Log.d(TAG, "Exception in reAuth"); - } - } - - runOnUiThread(new Runnable() { - @Override - public void run() { - progressDialog.dismiss(); - } - }); - - Thread getBookBags = new Thread(getBookbagsRunnable); - getBookBags.start(); - } - } - }); - - if (name.length() > 1) { - progressDialog = ProgressDialog.show(context, - getResources().getText(R.string.dialog_please_wait), - "Creating Bookbag"); - createBookbag.start(); - } else - Toast.makeText(context, - "Bookbag name must be at least 2 characters long", - Toast.LENGTH_SHORT).show(); - } - }); - - getBookbagsRunnable = new Runnable() { - - @Override - public void run() { - runOnUiThread(new Runnable() { - @Override - public void run() { - progressDialog = ProgressDialog.show(context, - getResources().getText(R.string.dialog_please_wait), - "Retrieving Bookbag data"); - } - }); - - try { - accountAccess.retrieveBookbags(); - } catch (SessionNotFoundException e) { - try { - if (accountAccess.reauthenticate(BookbagsListView.this)) - accountAccess.retrieveBookbags(); - } catch (Exception eauth) { - Log.d(TAG, "Exception in reAuth"); - } - } - bookBags = accountAccess.getBookbags(); - - runOnUiThread(new Runnable() { - - @Override - public void run() { - listAdapter.clear(); - for (int i = 0; i < bookBags.size(); i++) - listAdapter.add(bookBags.get(i)); - - progressDialog.dismiss(); - - if (bookBags.size() == 0) - Toast.makeText(context, "No data", - Toast.LENGTH_LONG); - - listAdapter.notifyDataSetChanged(); - } - }); - - } - }; - - new Thread(getBookbagsRunnable).start(); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - // TODO Auto-generated method stub - super.onActivityResult(requestCode, resultCode, data); - - switch (resultCode) { - - case BookBagDetails.RESULT_CODE_UPDATE: { - Thread getBookBags = new Thread(getBookbagsRunnable); - getBookBags.start(); - } - break; - - } - } - - class BookBagsArrayAdapter extends ArrayAdapter { - private static final String tag = "BookbagArrayAdapter"; - - private TextView name; - private TextView items; - private CheckBox shared; - private Button detailsButton; - - private List records = new ArrayList(); - - public BookBagsArrayAdapter(Context context, int textViewResourceId, - List objects) { - super(context, textViewResourceId, objects); - this.records = objects; - } - - public int getCount() { - return this.records.size(); - } - - public BookBag getItem(int index) { - return this.records.get(index); - } - - public View getView(int position, View convertView, ViewGroup parent) { - View row = convertView; - - // Get item - final BookBag record = getItem(position); - - // if it is the right type of view - if (row == null) { - - Log.d(tag, "Starting XML Row Inflation ... "); - LayoutInflater inflater = (LayoutInflater) this.getContext() - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - row = inflater.inflate(R.layout.bookbag_list_item, parent, - false); - Log.d(tag, "Successfully completed XML Row Inflation!"); - - } - - name = (TextView) row.findViewById(R.id.bookbag_name); - - items = (TextView) row.findViewById(R.id.bookbag_items); - - shared = (CheckBox) row.findViewById(R.id.bookbag_shared); - - detailsButton = (Button) row.findViewById(R.id.details_button); - - name.setText(record.name + ""); - - items.setText(record.items.size() + ""); - - shared.setChecked(record.shared); - - detailsButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - Intent intent = new Intent(context, BookBagDetails.class); - intent.putExtra("bookBag", record); - startActivityForResult(intent, 0); - - } - }); - - return row; - } - } -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/checkout/CircRecord.java b/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/checkout/CircRecord.java deleted file mode 100644 index 2e959729f7..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/checkout/CircRecord.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.accountAccess.checkout; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; - -import org.evergreen.android.globals.GlobalConfigs; -import org.opensrf.util.OSRFObject; - -/** - * This is a wrapper class that get the information out for a circ object - * - * @author daniel - * - */ -public class CircRecord { - - public static final int MVR_OBJ_TYPE = 1; - public static final int ACP_OBJ_TYPE = 2; - public static final int UNDEF_OBJ_TYPE = 0; - - public OSRFObject mvr = null; - - public OSRFObject acp = null; - - public OSRFObject circ = null; - - public int circ_info_type = UNDEF_OBJ_TYPE; - - public int circ_type; - - public static final int OUT = 0; - public static final int CLAIMS_RETURNED = 1; - public static final int LONG_OVERDUE = 2; - public static final int OVERDUE = 3; - public static final int LOST = 4; - - public int circ_id = -1; - - private Date circ_due_date = null; - - public CircRecord(OSRFObject circ, OSRFObject mvr, OSRFObject acp, - int circ_type, int circ_id) { - - this.circ = circ; - - // one of the acp or mvr will be null this will determine the circ - // OSRFObject type - this.acp = acp; - this.mvr = mvr; - - if (this.acp != null) - this.circ_info_type = ACP_OBJ_TYPE; - - if (this.mvr != null) - this.circ_info_type = MVR_OBJ_TYPE; - - this.circ_type = circ_type; - this.circ_id = circ_id; - this.circ_due_date = GlobalConfigs.parseDate(circ.getString("due_date")); - } - - public CircRecord(OSRFObject circ, int circ_type, int circ_id) { - this.circ = circ; - this.circ_type = circ_type; - this.circ_id = circ_id; - this.circ_due_date = GlobalConfigs.parseDate(circ.getString("due_date")); - } - - public String getAuthor() { - - String author = null; - - if (this.circ_info_type == MVR_OBJ_TYPE) - author = mvr.getString("author"); - if (this.circ_info_type == ACP_OBJ_TYPE) - author = acp.getString("dummy_author"); - - return author; - } - - public String getDueDate() { - - return circ_due_date.toLocaleString(); - } - - public Date getDueDateObject() { - return circ_due_date; - } - - public String getTitle() { - - String title = null; - - if (this.circ_info_type == MVR_OBJ_TYPE) - title = mvr.getString("title"); - if (this.circ_info_type == ACP_OBJ_TYPE) - title = acp.getString("dummy_title"); - - return title; - } - - public Integer getRenewals() { - - if (circ != null) - return circ.getInt("renewal_remaining"); - - return null; - } - - public Integer getTargetCopy() { - if (circ != null) - return circ.getInt("target_copy"); - - return null; - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/checkout/ItemsCheckOutListView.java b/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/checkout/ItemsCheckOutListView.java deleted file mode 100644 index d4e74b10fc..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/checkout/ItemsCheckOutListView.java +++ /dev/null @@ -1,367 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.accountAccess.checkout; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import android.opengl.Visibility; -import org.evergreen.android.R; -import org.evergreen.android.accountAccess.AccountAccess; -import org.evergreen.android.accountAccess.MaxRenewalsException; -import org.evergreen.android.accountAccess.ServerErrorMessage; -import org.evergreen.android.accountAccess.SessionNotFoundException; -import org.evergreen.android.searchCatalog.SearchCatalogListView; -import org.evergreen.android.views.AccountScreenDashboard; -import org.evergreen.android.views.splashscreen.SplashActivity; - -import android.app.Activity; -import android.app.ProgressDialog; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.ListView; -import android.widget.TextView; -import android.widget.Toast; - -public class ItemsCheckOutListView extends Activity { - - private final String TAG = ItemsCheckOutListView.class.getName(); - - private AccountAccess accountAccess = null; - - private ListView lv; - - private CheckOutArrayAdapter listAdapter = null; - - private ArrayList circRecords = null; - - private Context context; - - private ProgressDialog progressDialog; - - private Button homeButton; - - private Button myAccountButton; - - private TextView headerTitle; - - private TextView itemsNo; - - private Activity thisActivity; - - private TextView overdueItems; - - private Date currentDate; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (!SplashActivity.isAppInitialized()) { - SplashActivity.restartApp(this); - return; - } - - thisActivity = this; - setContentView(R.layout.checkout_list); - setTitle(R.string.checkout_items_title); - - currentDate = new Date(System.currentTimeMillis()); - - // header portion actions - myAccountButton = (Button) findViewById(R.id.my_account_button); - myAccountButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(getApplicationContext(), - AccountScreenDashboard.class); - startActivity(intent); - } - }); - - homeButton = (Button) findViewById(R.id.action_bar_home_button); - homeButton.setText(R.string.checkout_items_title); - homeButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(getApplicationContext(), - SearchCatalogListView.class); - startActivity(intent); - } - }); - // end header portion actions - - context = this; - itemsNo = (TextView) findViewById(R.id.checkout_items_number); - overdueItems = (TextView) findViewById(R.id.checkout_items_overdue); - accountAccess = AccountAccess.getAccountAccess(); - lv = (ListView) findViewById(R.id.checkout_items_list); - circRecords = new ArrayList(); - listAdapter = new CheckOutArrayAdapter(context, - R.layout.checkout_list_item, circRecords); - lv.setAdapter(listAdapter); - - Thread getCirc = new Thread(new Runnable() { - - @Override - public void run() { - - try { - circRecords = accountAccess.getItemsCheckedOut(); - } catch (SessionNotFoundException e) { - try { - if (accountAccess.reauthenticate(ItemsCheckOutListView.this)) - circRecords = accountAccess.getItemsCheckedOut(); - } catch (Exception eauth) { - Log.d(TAG, "Exception in reauth", eauth); - } - } - - runOnUiThread(new Runnable() { - - @Override - public void run() { - for (int i = 0; i < circRecords.size(); i++) - listAdapter.add(circRecords.get(i)); - - itemsNo.setText(" " + circRecords.size() + " "); - - // find overdue items - int overdueNo = 0; - for (int i = 0; i < circRecords.size(); i++) { - CircRecord circ = circRecords.get(i); - if (circ.getDueDateObject().compareTo(currentDate) < 0) - overdueNo++; - } - overdueItems.setText(" " + overdueNo); - - progressDialog.dismiss(); - - if (circRecords.size() == 0) - Toast.makeText(context, "No records", - Toast.LENGTH_LONG); - - listAdapter.notifyDataSetChanged(); - } - }); - } - }); - - progressDialog = new ProgressDialog(context); - progressDialog.setMessage("Retrieving circulation data"); - progressDialog.show(); - getCirc.start(); - } - - private void dismissProgress() { - if (progressDialog != null && progressDialog.isShowing()) - progressDialog.dismiss(); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - MenuInflater menuInflater = getMenuInflater(); - menuInflater.inflate(R.menu.checkout_menu, menu); - return super.onCreateOptionsMenu(menu); - - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - - return super.onOptionsItemSelected(item); - } - - class CheckOutArrayAdapter extends ArrayAdapter { - private static final String tag = "CheckoutArrayAdapter"; - - private TextView recordTitle; - private TextView recordAuthor; - private TextView recordDueDate; - private TextView recordRenewals; - private TextView renewButton; - - private List records = new ArrayList(); - - public CheckOutArrayAdapter(Context context, int textViewResourceId, - List objects) { - super(context, textViewResourceId, objects); - this.records = objects; - } - - public int getCount() { - return this.records.size(); - } - - public CircRecord getItem(int index) { - return this.records.get(index); - } - - public View getView(int position, View convertView, ViewGroup parent) { - View row = convertView; - - // Get item - final CircRecord record = getItem(position); - - // if it is the right type of view - if (row == null) { - - Log.d(tag, "Starting XML Row Inflation ... "); - LayoutInflater inflater = (LayoutInflater) this - .getContext().getSystemService( - Context.LAYOUT_INFLATER_SERVICE); - row = inflater.inflate(R.layout.checkout_list_item, parent, - false); - Log.d(tag, "Successfully completed XML Row Inflation!"); - - } - - // Get reference to TextView - title - recordTitle = (TextView) row.findViewById(R.id.checkout_record_title); - - // Get reference to TextView - author - recordAuthor = (TextView) row.findViewById(R.id.checkout_record_author); - - // Get reference to TextView - record Publisher date+publisher - recordDueDate = (TextView) row.findViewById(R.id.checkout_due_date); - - renewButton = (TextView) row.findViewById(R.id.renew_button); - final boolean renewable = record.getRenewals() > 0; - renewButton.setVisibility(renewable ? View.VISIBLE : View.GONE); - renewButton.setEnabled(renewable); - renewButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - if (!renewable) - return; - Thread renew = new Thread(new Runnable() { - - @Override - public void run() { - boolean refresh = true; - AccountAccess ac = AccountAccess - .getAccountAccess(); - - runOnUiThread(new Runnable() { - @Override - public void run() { - progressDialog = new ProgressDialog(context); - progressDialog.setMessage("Renewing item"); - progressDialog.show(); - } - }); - - try { - ac.renewCirc(record.getTargetCopy()); - } catch (MaxRenewalsException e1) { - runOnUiThread(new Runnable() { - - @Override - public void run() { - progressDialog.dismiss(); - Toast.makeText(context, - "Max renewals reached", - Toast.LENGTH_LONG).show(); - } - }); - - refresh = false; - } catch (ServerErrorMessage error) { - final String errorMessage = error.message; - runOnUiThread(new Runnable() { - - @Override - public void run() { - progressDialog.dismiss(); - Toast.makeText(context, - errorMessage, - Toast.LENGTH_LONG).show(); - } - }); - } catch (SessionNotFoundException e1) { - try { - if (accountAccess.reauthenticate(ItemsCheckOutListView.this)) - ac.renewCirc(record.getTargetCopy()); - } catch (Exception eauth) { - Log.d(TAG, "Exception in reauth", eauth); - } - } - runOnUiThread(new Runnable() { - @Override - public void run() { - Toast.makeText(context, getString(R.string.item_renewed), Toast.LENGTH_SHORT).show(); - } - }); - - if (refresh) { - try { - circRecords = accountAccess.getItemsCheckedOut(); - } catch (SessionNotFoundException e) { - try { - if (accountAccess.reauthenticate(ItemsCheckOutListView.this)) - circRecords = accountAccess.getItemsCheckedOut(); - } catch (Exception eauth) { - Log.d(TAG, "Exception in reauth", eauth); - } - } - - runOnUiThread(new Runnable() { - @Override - public void run() { - listAdapter.clear(); - for (int i = 0; i < circRecords.size(); i++) { - listAdapter.add(circRecords.get(i)); - } - progressDialog.dismiss(); - listAdapter.notifyDataSetChanged(); - } - }); - } - } - }); - - renew.start(); - } - }); - - // set text - recordTitle.setText(record.getTitle()); - recordAuthor.setText(record.getAuthor()); - recordDueDate.setText(getString(R.string.due) + ": " + record.getDueDate()); - Log.d(TAG, "title: " + record.getTitle()); - Log.d(TAG, "author: " + record.getAuthor()); - Log.d(TAG, "due: " + record.getDueDate()); - Log.d(TAG, "renew: " + record.getRenewals()); - - return row; - } - } -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/fines/FinesActivity.java b/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/fines/FinesActivity.java deleted file mode 100644 index 9264be07a7..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/fines/FinesActivity.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.accountAccess.fines; - -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.List; - -import org.evergreen.android.R; -import org.evergreen.android.accountAccess.AccountAccess; -import org.evergreen.android.accountAccess.SessionNotFoundException; -import org.evergreen.android.searchCatalog.SearchCatalogListView; -import org.evergreen.android.views.AccountScreenDashboard; -import org.evergreen.android.views.splashscreen.SplashActivity; - -import android.app.Activity; -import android.app.ProgressDialog; -import android.content.Context; -import android.content.Intent; -import android.graphics.Color; -import android.os.Bundle; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.ListView; -import android.widget.TextView; - -public class FinesActivity extends Activity { - - private TextView total_owned; - - private TextView total_paid; - - private TextView balance_owed; - - private ListView lv; - - private Runnable getFinesInfo; - - private AccountAccess ac; - - private ProgressDialog progressDialog; - - private OverdueMaterialsArrayAdapter listAdapter; - - private Button homeButton; - - private Button myAccountButton; - - private TextView headerTitle; - - private Context context; - - private DecimalFormat decimalFormater; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (!SplashActivity.isAppInitialized()) { - SplashActivity.restartApp(this); - return; - } - - setContentView(R.layout.fines); - - // header portion actions - myAccountButton = (Button) findViewById(R.id.my_account_button); - myAccountButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(getApplicationContext(), - AccountScreenDashboard.class); - startActivity(intent); - } - }); - - homeButton = (Button) findViewById(R.id.action_bar_home_button); - homeButton.setText(R.string.fines_title); - homeButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(getApplicationContext(), - SearchCatalogListView.class); - startActivity(intent); - } - }); - // end header portion actions - - decimalFormater = new DecimalFormat("#0.00"); - lv = (ListView) findViewById(R.id.fines_overdue_materials_list); - - total_owned = (TextView) findViewById(R.id.fines_total_owned); - total_paid = (TextView) findViewById(R.id.fines_total_paid); - balance_owed = (TextView) findViewById(R.id.fined_balance_owed); - context = this; - - ac = AccountAccess.getAccountAccess(); - - ArrayList finesRecords = new ArrayList(); - listAdapter = new OverdueMaterialsArrayAdapter(context, - R.layout.fines_list_item, finesRecords); - lv.setAdapter(listAdapter); - - progressDialog = ProgressDialog.show(this, - getResources().getText(R.string.dialog_please_wait), - "Retrieving fines"); - - getFinesInfo = new Runnable() { - @Override - public void run() { - - float[] finesR = null; - try { - finesR = ac.getFinesSummary(); - } catch (SessionNotFoundException e) { - try { - if (ac.reauthenticate(FinesActivity.this)) - finesR = ac.getFinesSummary(); - } catch (Exception e1) { - } - } - - ArrayList frecords = null; - try { - frecords = ac.getTransactions(); - } catch (SessionNotFoundException e) { - try { - if (ac.reauthenticate(FinesActivity.this)) - frecords = ac.getTransactions(); - } catch (Exception e1) { - } - } - - final ArrayList finesRecords = frecords; - final float[] fines = finesR; - runOnUiThread(new Runnable() { - @Override - public void run() { - - listAdapter.clear(); - - for (int i = 0; i < finesRecords.size(); i++) - listAdapter.add(finesRecords.get(i)); - - listAdapter.notifyDataSetChanged(); - - total_owned.setText(decimalFormater.format(fines[0])); - total_paid.setText(decimalFormater.format(fines[1])); - balance_owed.setText(decimalFormater.format(fines[2])); - progressDialog.dismiss(); - } - }); - } - }; - - Thread getFinesTh = new Thread(getFinesInfo); - getFinesTh.start(); - } - - class OverdueMaterialsArrayAdapter extends ArrayAdapter { - private static final String tag = "CheckoutArrayAdapter"; - - private TextView fineTitle; - private TextView fineAuthor; - private TextView fineBalanceOwed; - private TextView fineStatus; - - private List records = new ArrayList(); - - public OverdueMaterialsArrayAdapter(Context context, - int textViewResourceId, List objects) { - super(context, textViewResourceId, objects); - this.records = objects; - } - - public int getCount() { - return this.records.size(); - } - - public FinesRecord getItem(int index) { - return this.records.get(index); - } - - public View getView(int position, View convertView, ViewGroup parent) { - View row = convertView; - - // Get item - final FinesRecord record = getItem(position); - - if (row == null) { - - Log.d(tag, "Starting XML view more infaltion ... "); - LayoutInflater inflater = (LayoutInflater) this.getContext() - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - row = inflater.inflate(R.layout.fines_list_item, parent, false); - Log.d(tag, "Successfully completed XML view more Inflation!"); - - } - // Get reference to TextView - title - fineTitle = (TextView) row.findViewById(R.id.fines_title); - - // Get reference to TextView author - fineAuthor = (TextView) row.findViewById(R.id.fines_author); - - // Get hold status - fineBalanceOwed = (TextView) row - .findViewById(R.id.fines_balance_owed); - - fineStatus = (TextView) row.findViewById(R.id.fines_status); - // set text - - // set raw information - fineTitle.setText(record.title); - fineAuthor.setText(record.author); - fineBalanceOwed.setText(decimalFormater.format(record.balance_owed)); - // status.setText(record.getHoldStatus()); - fineStatus.setText(record.getStatus()); - - return row; - } - } -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/fines/FinesRecord.java b/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/fines/FinesRecord.java deleted file mode 100644 index 1e8de96a02..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/fines/FinesRecord.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.accountAccess.fines; - -import java.util.Date; - -import org.evergreen.android.globals.GlobalConfigs; -import org.opensrf.util.OSRFObject; - -public class FinesRecord { - - public String title; - - public String author; - - public Date checkoutDate; - - public Date dueDate; - - public Date dateReturned; - - public Double balance_owed; - - private Date checkin_time; - - // types are grocery and circulation - private int type; - - public static int FINE_GROCERY_TYPE = 1; - public static int FINE_CIRCULATION = 2; - - public FinesRecord(OSRFObject circ, OSRFObject mvr_record, - OSRFObject mbts_transaction) { - - if (mbts_transaction.get("xact_type").toString().equals("circulation")) { - - title = mvr_record.getString("title"); - author = mvr_record.getString("author"); - - if (circ.get("checkin_time") != null) { - checkin_time = GlobalConfigs.parseDate(circ - .getString("checkin_time")); - } else - checkin_time = null; - - } else { - // grocery - title = "Grocery billing"; - author = mbts_transaction.getString("last_billing_note"); - - } - - try{ - balance_owed =Double.parseDouble(mbts_transaction.getString("total_owed")); - }catch(Exception e){ - System.err.println("Error in total owed string to double conversion " + e.getMessage()); - } - } - - // if returned or fines still acumulating - public String getStatus() { - - if (checkin_time != null) - return "returned"; - - return "fines accruing"; - - } -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/holds/HoldDetails.java b/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/holds/HoldDetails.java deleted file mode 100644 index 48fbb44a85..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/holds/HoldDetails.java +++ /dev/null @@ -1,433 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.accountAccess.holds; - -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; - -import android.util.Log; -import org.evergreen.android.R; -import org.evergreen.android.accountAccess.AccountAccess; -import org.evergreen.android.accountAccess.SessionNotFoundException; -import org.evergreen.android.globals.GlobalConfigs; -import org.evergreen.android.searchCatalog.SearchCatalogListView; -import org.evergreen.android.views.AccountScreenDashboard; -import org.evergreen.android.views.splashscreen.SplashActivity; - -import android.app.Activity; -import android.app.AlertDialog; -import android.app.AlertDialog.Builder; -import android.app.DatePickerDialog; -import android.app.ProgressDialog; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.graphics.Color; -import android.os.Bundle; -import android.text.format.DateFormat; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemSelectedListener; -import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.CheckBox; -import android.widget.CompoundButton; -import android.widget.CompoundButton.OnCheckedChangeListener; -import android.widget.DatePicker; -import android.widget.EditText; -import android.widget.Spinner; -import android.widget.TextView; -import android.widget.Toast; - -public class HoldDetails extends Activity { - - private final String TAG = HoldDetails.class.getName(); - - public static final int RESULT_CODE_DELETE_HOLD = 5; - - public static final int RESULT_CODE_UPDATE_HOLD = 6; - - public static final int RESULT_CODE_CANCEL = 7; - - private TextView recipient; - - private TextView title; - - private TextView author; - - private TextView physical_description; - - private TextView screen_title; - - private AccountAccess accountAccess; - - private EditText expiration_date; - - private Button updateHold; - - private Button cancelHold; - - private Button back; - - private DatePickerDialog datePicker = null; - - private CheckBox suspendHold; - - private Spinner orgSelector; - - private DatePickerDialog thaw_datePicker = null; - - private EditText thaw_date_edittext; - - private Date expire_date = null; - - private Date thaw_date = null; - - private Context context; - - private int selectedOrgPos = 0; - - public Runnable updateHoldRunnable; - - private ProgressDialog progressDialog; - - private GlobalConfigs globalConfigs; - - private Button homeButton; - - private Button myAccountButton; - - private TextView headerTitle; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (!SplashActivity.isAppInitialized()) { - SplashActivity.restartApp(this); - return; - } - - context = this; - setContentView(R.layout.hold_details); - globalConfigs = GlobalConfigs.getGlobalConfigs(this); - - myAccountButton = (Button) findViewById(R.id.my_account_button); - myAccountButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(getApplicationContext(), - AccountScreenDashboard.class); - startActivity(intent); - } - }); - - homeButton = (Button) findViewById(R.id.action_bar_home_button); - homeButton.setText(R.string.hold_details_title); - homeButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(getApplicationContext(), - SearchCatalogListView.class); - startActivity(intent); - } - }); - - final HoldRecord record = (HoldRecord) getIntent() - .getSerializableExtra("holdRecord"); - - Log.d(TAG, "Record " + record + " " + record.title + " " - + record.ahr); - - accountAccess = AccountAccess.getAccountAccess(); - - recipient = (TextView) findViewById(R.id.hold_recipient); - title = (TextView) findViewById(R.id.hold_title); - author = (TextView) findViewById(R.id.hold_author); - physical_description = (TextView) findViewById(R.id.hold_physical_description); - cancelHold = (Button) findViewById(R.id.cancel_hold_button); - updateHold = (Button) findViewById(R.id.update_hold_button); - back = (Button) findViewById(R.id.back_button); - suspendHold = (CheckBox) findViewById(R.id.hold_suspend_hold); - orgSelector = (Spinner) findViewById(R.id.hold_pickup_location); - expiration_date = (EditText) findViewById(R.id.hold_expiration_date); - thaw_date_edittext = (EditText) findViewById(R.id.hold_thaw_date); - - recipient.setText(accountAccess.userName); - title.setText(record.title); - author.setText(record.author); - if (record.recordInfo != null) - physical_description - .setText(record.recordInfo.physical_description); - - // set record info - suspendHold.setChecked(record.suspended); - - if (record.thaw_date != null) { - thaw_date = record.thaw_date; - thaw_date_edittext.setText(DateFormat.format("MMMM dd, yyyy", - thaw_date)); - } - if (record.expire_time != null) { - expire_date = record.expire_time; - expiration_date.setText(DateFormat.format("MMMM dd, yyyy", - expire_date)); - } - - // hide edit text - if (record.thaw_date == null) - disableView(thaw_date_edittext); - - Log.d(TAG, record.title + " " + record.author); - - back.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - finish(); - } - }); - - cancelHold.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - - Builder confirmationDialogBuilder = new AlertDialog.Builder( - context); - confirmationDialogBuilder - .setMessage(R.string.cancel_hold_dialog_message); - - confirmationDialogBuilder.setNegativeButton( - android.R.string.no, null); - confirmationDialogBuilder.setPositiveButton( - android.R.string.yes, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, - int which) { - - Log.d(TAG, "Remove hold with id" - + record.ahr.getInt("id")); - - progressDialog = ProgressDialog.show(context, - getResources().getText(R.string.dialog_please_wait), - "Canceling hold"); - Thread cancelHoldThread = new Thread( - new Runnable() { - - @Override - public void run() { - - try { - accountAccess - .cancelHold(record.ahr); - } catch (SessionNotFoundException e) { - try { - if (accountAccess.reauthenticate(HoldDetails.this)) - accountAccess - .cancelHold(record.ahr); - } catch (Exception eauth) { - Log.d(TAG, "Exception in reAuth"); - } - } - - runOnUiThread(new Runnable() { - @Override - public void run() { - progressDialog - .dismiss(); - setResult(RESULT_CODE_DELETE_HOLD); - - finish(); - } - }); - } - }); - cancelHoldThread.start(); - - } - }); - confirmationDialogBuilder.create().show(); - - } - }); - - updateHoldRunnable = new Runnable() { - @Override - public void run() { - // update new values - String expire_date_s = null; - String thaw_date_s = null; - if (expire_date != null) - expire_date_s = GlobalConfigs.getStringDate(expire_date); - if (thaw_date != null) - thaw_date_s = GlobalConfigs.getStringDate(thaw_date); - - try { - accountAccess.updateHold(record.ahr, selectedOrgPos, - suspendHold.isChecked(), - expire_date_s, thaw_date_s); - } catch (SessionNotFoundException e) { - try { - if (accountAccess.reauthenticate(HoldDetails.this)) - accountAccess.updateHold(record.ahr, - selectedOrgPos, - suspendHold.isChecked(), expire_date_s, - thaw_date_s); - } catch (Exception eauth) { - Log.d(TAG, "Exception in reAuth"); - } - } - - runOnUiThread(new Runnable() { - @Override - public void run() { - progressDialog.dismiss(); - Toast.makeText(context, "Hold updated", - Toast.LENGTH_SHORT); - setResult(RESULT_CODE_UPDATE_HOLD); - finish(); - } - }); - } - }; - - updateHold.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - progressDialog = ProgressDialog.show(context, - getResources().getText(R.string.dialog_please_wait), - "Updating hold"); - Thread updateHoldThread = new Thread(updateHoldRunnable); - updateHoldThread.start(); - } - }); - - suspendHold.setOnCheckedChangeListener(new OnCheckedChangeListener() { - - @Override - public void onCheckedChanged(CompoundButton buttonView, - boolean isChecked) { - - if (isChecked) { - enableView(thaw_date_edittext); - } else { - disableView(thaw_date_edittext); - } - } - }); - Calendar cal = Calendar.getInstance(); - - datePicker = new DatePickerDialog(this, - new DatePickerDialog.OnDateSetListener() { - - public void onDateSet(DatePicker view, int year, - int monthOfYear, int dayOfMonth) { - - Date chosenDate = new Date(year - 1900, monthOfYear, - dayOfMonth); - expire_date = chosenDate; - CharSequence strDate = DateFormat.format( - "MMMM dd, yyyy", chosenDate); - expiration_date.setText(strDate); - // set current date - } - }, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), - cal.get(Calendar.DAY_OF_MONTH)); - - expiration_date.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - datePicker.show(); - } - }); - - thaw_datePicker = new DatePickerDialog(this, - new DatePickerDialog.OnDateSetListener() { - - public void onDateSet(DatePicker view, int year, - int monthOfYear, int dayOfMonth) { - - Date chosenDate = new Date(year - 1900, monthOfYear, - dayOfMonth); - thaw_date = chosenDate; - CharSequence strDate = DateFormat.format( - "MMMM dd, yyyy", chosenDate); - thaw_date_edittext.setText(strDate); - // set current date - } - }, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), - cal.get(Calendar.DAY_OF_MONTH)); - - thaw_date_edittext.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - thaw_datePicker.show(); - } - }); - - ArrayList list = new ArrayList(); - for (int i = 0; i < globalConfigs.organisations.size(); i++) { - list.add(globalConfigs.organisations.get(i).padding - + globalConfigs.organisations.get(i).name); - - if (globalConfigs.organisations.get(i).id == record.pickup_lib) - selectedOrgPos = i; - } - ArrayAdapter adapter = new ArrayAdapter(this, - R.layout.spinner_layout, list); - orgSelector.setAdapter(adapter); - - orgSelector.setSelection(selectedOrgPos); - - orgSelector.setOnItemSelectedListener(new OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView arg0, View arg1, int ID, - long arg3) { - - selectedOrgPos = ID; - - } - - public void onNothingSelected(android.widget.AdapterView arg0) { - } - }); - } - - public void disableView(View view) { - - // view.setFocusable(false); - view.setFocusable(false); - - view.setBackgroundColor(Color.argb(255, 100, 100, 100)); - // view.setVisibility(View.INVISIBLE); - } - - public void enableView(View view) { - // view.setVisibility(View.VISIBLE); - - view.setFocusableInTouchMode(true); - - view.setBackgroundColor(Color.argb(255, 255, 255, 255)); - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/holds/HoldRecord.java b/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/holds/HoldRecord.java deleted file mode 100644 index d9f2e2d72a..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/holds/HoldRecord.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.accountAccess.holds; - -import java.io.Serializable; -import java.util.Date; - -import org.evergreen.android.R; -import org.evergreen.android.globals.GlobalConfigs; -import org.evergreen.android.searchCatalog.RecordInfo; -import org.opensrf.util.OSRFObject; -import android.content.res.Resources; - -public class HoldRecord implements Serializable { - - private Integer requestLibID = null; - - private Integer pickupLibID = null; - - public String holdType = null; - // id for target object - public Integer target = null; - public Date expire_time = null; - - public String title = null; - - public String author = null; - - public String types_of_resource; - - // only for P types - public String part_label = null; - - public Integer status = null; - - public Boolean active = null; - - // must also be serializable - public OSRFObject ahr = null; - // record info with more etails - public RecordInfo recordInfo = null; - - public boolean email_notification = false; - - public String phone_notification = null; - - public boolean suspended = false; - - public Date thaw_date; - - public int pickup_lib; - - public Integer potentialCopies; - - public Integer estimatedWaitInSeconds; - - public Integer queuePosition; - - public Integer totalHolds; - - public HoldRecord(OSRFObject ahr) { - - this.target = ahr.getInt("target"); - this.holdType = ahr.getString("hold_type"); - - this.ahr = ahr; - - this.expire_time = GlobalConfigs.parseDate(ahr.getString("expire_time")); - this.thaw_date = GlobalConfigs.parseDate(ahr.getString("thaw_date")); - this.email_notification = GlobalConfigs.parseBoolean(ahr.getString("email_notify")); - this.phone_notification = ahr.getString("phone_notify"); - this.suspended = GlobalConfigs.parseBoolean(ahr.getString("frozen")); - pickup_lib = ahr.getInt("pickup_lib"); - - } - - // Retreive hold status in text - public String getHoldStatus(Resources res) { - // Constants from Holds.pm and logic from hold_status.tt2 - // -1 on error (for now), - // 1 for 'waiting for copy to become available', - // 2 for 'waiting for copy capture', - // 3 for 'in transit', - // 4 for 'arrived', - // 5 for 'hold-shelf-delay' - // 6 for 'canceled' - // 7 for 'suspended' - // 8 for 'captured, on wrong hold shelf' - if (status == 4) { - return "Available"; - } else if (estimatedWaitInSeconds > 0) { - int days = (int)Math.ceil((double)estimatedWaitInSeconds / 86400.0); - return "Estimated wait "+days+" day wait"; - } else if (status == 3 || status == 8) { - return "In Transit"; - } else if (status < 3) { - return "Waiting for copy\n" - + res.getQuantityString(R.plurals.number_of_holds, totalHolds, totalHolds) + " on " - + res.getQuantityString(R.plurals.number_of_copies, potentialCopies, potentialCopies) - + "\n" - + "Queue position: " + queuePosition; - } else { - return ""; - } - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/holds/HoldsListView.java b/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/holds/HoldsListView.java deleted file mode 100644 index 0ffacb2e2a..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/holds/HoldsListView.java +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.accountAccess.holds; - -import java.util.ArrayList; -import java.util.List; - -import org.evergreen.android.R; -import org.evergreen.android.accountAccess.AccountAccess; -import org.evergreen.android.accountAccess.SessionNotFoundException; -import org.evergreen.android.globals.GlobalConfigs; -import org.evergreen.android.searchCatalog.ImageDownloader; -import org.evergreen.android.searchCatalog.SearchCatalogListView; -import org.evergreen.android.views.AccountScreenDashboard; -import org.evergreen.android.views.splashscreen.SplashActivity; - -import android.app.Activity; -import android.app.ProgressDialog; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.ListView; -import android.widget.TextView; - -public class HoldsListView extends Activity { - - private final String TAG = HoldsListView.class.getName(); - - private AccountAccess accountAccess = null; - - private ListView lv; - - private HoldsArrayAdapter listAdapter = null; - - private List holdRecords = null; - - private Context context; - - Runnable getHoldsRunnable = null; - - private Button homeButton; - - private Button myAccountButton; - - private TextView headerTitle; - - private TextView holdsNoText; - - private ProgressDialog progressDialog; - - private ImageDownloader imageDownloader; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (!SplashActivity.isAppInitialized()) { - SplashActivity.restartApp(this); - return; - } - - setContentView(R.layout.holds_list); - - // header portion actions - myAccountButton = (Button) findViewById(R.id.my_account_button); - myAccountButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(getApplicationContext(), - AccountScreenDashboard.class); - startActivity(intent); - } - }); - - homeButton = (Button) findViewById(R.id.action_bar_home_button); - homeButton.setText(R.string.hold_items_title); - homeButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(getApplicationContext(), - SearchCatalogListView.class); - startActivity(intent); - } - }); - // end header portion actions - - holdsNoText = (TextView) findViewById(R.id.holds_number); - - imageDownloader = new ImageDownloader(40, 40, false); - - lv = (ListView) findViewById(R.id.holds_item_list); - context = this; - accountAccess = AccountAccess.getAccountAccess(); - - holdRecords = new ArrayList(); - listAdapter = new HoldsArrayAdapter(context, R.layout.holds_list_item, - holdRecords); - lv.setAdapter(listAdapter); - - getHoldsRunnable = new Runnable() { - @Override - public void run() { - - try { - holdRecords = accountAccess.getHolds(); - } catch (SessionNotFoundException e) { - try { - if (accountAccess.reauthenticate(HoldsListView.this)) - holdRecords = accountAccess.getHolds(); - } catch (Exception eauth) { - Log.d(TAG, "Exception in reauth"); - } - } - - runOnUiThread(new Runnable() { - @Override - public void run() { - listAdapter.clear(); - - for (int i = 0; i < holdRecords.size(); i++) - listAdapter.add(holdRecords.get(i)); - - holdsNoText.setText(" " + listAdapter.getCount()); - progressDialog.dismiss(); - listAdapter.notifyDataSetChanged(); - } - }); - } - }; - - progressDialog = new ProgressDialog(context); - progressDialog.setMessage("Loading holds"); - progressDialog.show(); - - // thread to retrieve holds - Thread getHoldsThread = new Thread(getHoldsRunnable); - getHoldsThread.start(); - - lv.setOnItemClickListener(new OnItemClickListener() { - - @Override - public void onItemClick(AdapterView arg0, View arg1, - int position, long arg3) { - HoldRecord record = (HoldRecord) lv.getItemAtPosition(position); - - Intent intent = new Intent(getApplicationContext(), - HoldDetails.class); - - intent.putExtra("holdRecord", record); - - // doae not matter request code, only result code - startActivityForResult(intent, 0); - } - }); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - // TODO Auto-generated method stub - super.onActivityResult(requestCode, resultCode, data); - - switch (resultCode) { - - case HoldDetails.RESULT_CODE_CANCEL: - // nothing - Log.d(TAG, "Do nothing"); - break; - - case HoldDetails.RESULT_CODE_DELETE_HOLD: - case HoldDetails.RESULT_CODE_UPDATE_HOLD: - // refresh ui - progressDialog = new ProgressDialog(context); - progressDialog.setMessage("Loading holds"); - progressDialog.show(); - // thread to retrieve holds - Thread getHoldsThread = new Thread(getHoldsRunnable); - getHoldsThread.start(); - Log.d(TAG, "Update on result "+resultCode); - break; - } - } - - class HoldsArrayAdapter extends ArrayAdapter { - private static final String tag = "CheckoutArrayAdapter"; - - private TextView holdTitle; - private TextView holdAuthor; - private TextView status; - private ImageView hold_icon; - - private List records = new ArrayList(); - - public HoldsArrayAdapter(Context context, int textViewResourceId, - List objects) { - super(context, textViewResourceId, objects); - this.records = objects; - } - - public int getCount() { - return this.records.size(); - } - - public HoldRecord getItem(int index) { - return this.records.get(index); - } - - public View getView(int position, View convertView, ViewGroup parent) { - View row = convertView; - - // Get item - final HoldRecord record = getItem(position); - - if (row == null) { - - Log.d(tag, "Starting XML view more infaltion ... "); - LayoutInflater inflater = (LayoutInflater) this.getContext() - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - row = inflater.inflate(R.layout.holds_list_item, parent, false); - Log.d(tag, "Successfully completed XML view more Inflation!"); - - } - - hold_icon = (ImageView) row.findViewById(R.id.hold_resource_icon); - - // Get reference to TextView - title - holdTitle = (TextView) row.findViewById(R.id.hold_title); - - // Get reference to TextView author - holdAuthor = (TextView) row.findViewById(R.id.hold_author); - - // Get hold status - status = (TextView) row.findViewById(R.id.hold_status); - - // set text - String imageResourceHref = GlobalConfigs.httpAddress - + GlobalConfigs.hold_icon_address - + record.types_of_resource + ".jpg"; - - if (imageResourceHref.contains(" ")) { - imageResourceHref = imageResourceHref.replace(" ", "%20"); - } - - imageDownloader.download(imageResourceHref, hold_icon); - - // set raw information - holdTitle.setText(record.title); - holdAuthor.setText(record.author); - status.setText(record.getHoldStatus(getResources())); - - return row; - } - } -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/holds/PlaceHold.java b/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/holds/PlaceHold.java deleted file mode 100644 index 82d083860e..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/accountAccess/holds/PlaceHold.java +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.accountAccess.holds; - -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; - -import android.util.Log; -import org.evergreen.android.R; -import org.evergreen.android.accountAccess.AccountAccess; -import org.evergreen.android.accountAccess.SessionNotFoundException; -import org.evergreen.android.globals.GlobalConfigs; -import org.evergreen.android.searchCatalog.RecordInfo; -import org.evergreen.android.searchCatalog.SearchCatalogListView; -import org.evergreen.android.views.AccountScreenDashboard; -import org.evergreen.android.views.splashscreen.SplashActivity; - -import android.app.Activity; -import android.app.DatePickerDialog; -import android.app.ProgressDialog; -import android.content.Context; -import android.content.Intent; -import android.graphics.Color; -import android.os.Bundle; -import android.text.format.DateFormat; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemSelectedListener; -import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.CheckBox; -import android.widget.CompoundButton; -import android.widget.CompoundButton.OnCheckedChangeListener; -import android.widget.DatePicker; -import android.widget.EditText; -import android.widget.Spinner; -import android.widget.TextView; -import android.widget.Toast; - -public class PlaceHold extends Activity { - - private final String TAG = PlaceHold.class.getName(); - - private TextView recipient; - - private TextView title; - - private TextView author; - - private TextView physical_description; - - private TextView screen_title; - - private AccountAccess accountAccess; - - private EditText expiration_date; - - private EditText phone_number; - - private CheckBox phone_notification; - - private CheckBox email_notification; - - private Button placeHold; - - private Button cancel; - - private CheckBox suspendHold; - - private Spinner orgSelector; - - private DatePickerDialog datePicker = null; - - private DatePickerDialog thaw_datePicker = null; - - private EditText thaw_date_edittext; - - private Date expire_date = null; - - private Date thaw_date = null; - - private Runnable placeHoldRunnable; - - private GlobalConfigs globalConfigs = null; - - private int selectedOrgPos = 0; - - private Button homeButton; - - private Button myAccountButton; - - private TextView headerTitle; - - private ProgressDialog progressDialog; - - private Context context; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (!SplashActivity.isAppInitialized()) { - SplashActivity.restartApp(this); - return; - } - - setContentView(R.layout.place_hold); - globalConfigs = GlobalConfigs.getGlobalConfigs(this); - RecordInfo record = (RecordInfo) getIntent().getSerializableExtra( - "recordInfo"); - - myAccountButton = (Button) findViewById(R.id.my_account_button); - myAccountButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(getApplicationContext(), - AccountScreenDashboard.class); - startActivity(intent); - } - }); - - homeButton = (Button) findViewById(R.id.action_bar_home_button); - homeButton.setText(R.string.hold_place_title); - homeButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(getApplicationContext(), - SearchCatalogListView.class); - startActivity(intent); - } - }); - - context = this; - - accountAccess = AccountAccess.getAccountAccess(); - - recipient = (TextView) findViewById(R.id.hold_recipient); - title = (TextView) findViewById(R.id.hold_title); - author = (TextView) findViewById(R.id.hold_author); - physical_description = (TextView) findViewById(R.id.hold_physical_description); - cancel = (Button) findViewById(R.id.cancel_hold); - placeHold = (Button) findViewById(R.id.place_hold); - expiration_date = (EditText) findViewById(R.id.hold_expiration_date); - phone_notification = (CheckBox) findViewById(R.id.hold_enable_phone_notification); - phone_number = (EditText) findViewById(R.id.hold_contact_telephone); - email_notification = (CheckBox) findViewById(R.id.hold_enable_email_notification); - suspendHold = (CheckBox) findViewById(R.id.hold_suspend_hold); - orgSelector = (Spinner) findViewById(R.id.hold_pickup_location); - thaw_date_edittext = (EditText) findViewById(R.id.hold_thaw_date); - - recipient.setText(accountAccess.userName); - title.setText(record.title); - author.setText(record.author); - physical_description.setText(record.physical_description); - - // hide edit text - disableView(thaw_date_edittext); - disableView(phone_number); - - cancel.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - finish(); - } - }); - - final Integer record_id = record.doc_id; - - placeHoldRunnable = new Runnable() { - - @Override - public void run() { - - runOnUiThread(new Runnable() { - @Override - public void run() { - progressDialog = ProgressDialog.show(context, - getResources().getText(R.string.dialog_please_wait), - "Placing hold"); - } - }); - // TODO verify hold possible - - // accountAccess.getHoldPreCreateInfo(record_id, 4); - // accountAccess.isHoldPossible(4, record_id); - - String expire_date_s = null; - String thaw_date_s = null; - if (expire_date != null) - expire_date_s = GlobalConfigs.getStringDate(expire_date); - if (thaw_date != null) - thaw_date_s = GlobalConfigs.getStringDate(thaw_date); - - Log.d(TAG, "date expire: " + expire_date_s + " " - + expire_date); - int selectedOrgID = -1; - if (globalConfigs.organisations.size() > selectedOrgPos) - selectedOrgID = globalConfigs.organisations - .get(selectedOrgPos).id; - - String[] stringResponse = new String[] { "false" }; - try { - stringResponse = accountAccess.createHold(record_id, - selectedOrgID, email_notification.isChecked(), - phone_notification.isChecked(), phone_number - .getText().toString(), suspendHold - .isChecked(), expire_date_s, thaw_date_s); - } catch (SessionNotFoundException e) { - try { - if (accountAccess.reauthenticate(PlaceHold.this)) - stringResponse = accountAccess.createHold( - record_id, selectedOrgID, - email_notification.isChecked(), - phone_notification.isChecked(), - phone_number.getText().toString(), - suspendHold.isChecked(), expire_date_s, - thaw_date_s); - } catch (Exception e1) { - } - } - - final String[] holdPlaced = stringResponse; - - runOnUiThread(new Runnable() { - @Override - public void run() { - progressDialog.dismiss(); - - if (holdPlaced[0].equals("true")) { - Toast.makeText(context, "Hold Succesfully placed", - Toast.LENGTH_LONG).show(); - finish(); - } else - Toast.makeText(context, - "Error in placing hold : " + holdPlaced[2], - Toast.LENGTH_LONG).show(); - - } - }); - } - }; - - placeHold.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - - Thread placeholdThread = new Thread(placeHoldRunnable); - placeholdThread.start(); - } - }); - - phone_notification - .setOnCheckedChangeListener(new OnCheckedChangeListener() { - - @Override - public void onCheckedChanged(CompoundButton buttonView, - boolean isChecked) { - - if (isChecked) { - enableView(phone_number); - } else - disableView(phone_number); - } - }); - - suspendHold.setOnCheckedChangeListener(new OnCheckedChangeListener() { - - @Override - public void onCheckedChanged(CompoundButton buttonView, - boolean isChecked) { - - if (isChecked) { - enableView(thaw_date_edittext); - } else { - disableView(thaw_date_edittext); - } - } - }); - - Calendar cal = Calendar.getInstance(); - - datePicker = new DatePickerDialog(this, - new DatePickerDialog.OnDateSetListener() { - - public void onDateSet(DatePicker view, int year, - int monthOfYear, int dayOfMonth) { - - Date chosenDate = new Date(year - 1900, monthOfYear, - dayOfMonth); - expire_date = chosenDate; - CharSequence strDate = DateFormat.format( - "MMMM dd, yyyy", chosenDate); - expiration_date.setText(strDate); - // set current date - } - }, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), - cal.get(Calendar.DAY_OF_MONTH)); - - expiration_date.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - datePicker.show(); - } - }); - - thaw_datePicker = new DatePickerDialog(this, - new DatePickerDialog.OnDateSetListener() { - - public void onDateSet(DatePicker view, int year, - int monthOfYear, int dayOfMonth) { - - Date chosenDate = new Date(year - 1900, monthOfYear, - dayOfMonth); - thaw_date = chosenDate; - CharSequence strDate = DateFormat.format( - "MMMM dd, yyyy", chosenDate); - thaw_date_edittext.setText(strDate); - // set current date - } - }, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), - cal.get(Calendar.DAY_OF_MONTH)); - - thaw_date_edittext.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - thaw_datePicker.show(); - } - }); - - ArrayList list = new ArrayList(); - for (int i = 0; i < globalConfigs.organisations.size(); i++) { - list.add(globalConfigs.organisations.get(i).padding - + globalConfigs.organisations.get(i).name); - - if (globalConfigs.organisations.get(i).level - 1 == 0) - selectedOrgPos = i; - } - ArrayAdapter adapter = new ArrayAdapter(this, - android.R.layout.simple_spinner_item, list); - orgSelector.setAdapter(adapter); - - orgSelector.setSelection(selectedOrgPos); - - orgSelector.setOnItemSelectedListener(new OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView arg0, View arg1, int ID, - long arg3) { - - selectedOrgPos = ID; - - } - - public void onNothingSelected(android.widget.AdapterView arg0) { - } - }); - } - - public void disableView(View view) { - - // view.setFocusable(false); - view.setFocusable(false); - - view.setBackgroundColor(Color.argb(255, 100, 100, 100)); - // view.setVisibility(View.INVISIBLE); - } - - public void enableView(View view) { - // view.setVisibility(View.VISIBLE); - - view.setFocusableInTouchMode(true); - - view.setBackgroundColor(Color.argb(255, 255, 255, 255)); - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/CaptureActivity.java b/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/CaptureActivity.java deleted file mode 100755 index 015975b819..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/CaptureActivity.java +++ /dev/null @@ -1,212 +0,0 @@ -package org.evergreen.android.barcodescan; - -import java.io.IOException; -import java.util.Vector; - -import org.evergreen.android.R; -import org.evergreen.android.barcodescan.camera.CameraManager; -import org.evergreen.android.views.splashscreen.SplashActivity; - -import android.app.Activity; -import android.app.AlertDialog; -import android.content.DialogInterface; -import android.content.Intent; -import android.graphics.Bitmap; -import android.os.Bundle; -import android.os.Handler; -import android.util.Log; -import android.view.Menu; -import android.view.SurfaceHolder; -import android.view.SurfaceView; -import android.view.Window; -import android.view.WindowManager; -import android.widget.Toast; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.Result; - -public class CaptureActivity extends Activity implements SurfaceHolder.Callback { - - private static final String TAG = CaptureActivity.class.getSimpleName(); - - private ViewfinderView viewfinderView; - - private CaptureActivityHandler handler; - - private CameraManager cameraManager; - private boolean hasSurface; - private Vector decodeFormats; - // private HistoryManager historyManager; - private Result lastResult; - private String characterSet; - public static final int BARCODE_SEARCH = 1; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (!SplashActivity.isAppInitialized()) { - SplashActivity.restartApp(this); - return; - } - - // Remove title bar - this.requestWindowFeature(Window.FEATURE_NO_TITLE); - - // Remove notification bar - this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - - setContentView(R.layout.barcode_scan); - - Log.d("BARCODE","Start application 1"); - Window window = getWindow(); - window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - - // init camera manager - cameraManager = new CameraManager(getApplication()); - hasSurface = false; - handler = null; - - viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view); - - viewfinderView.setCameraManager(cameraManager); - //database = new DBHelper(this); - - Log.d("BARCODE","Start application 2"); - } - - - @Override - public void onResume() { - super.onResume(); - - SurfaceView surfaceView = (SurfaceView) findViewById(R.id.camera_view); - SurfaceHolder surfaceHolder = surfaceView.getHolder(); - if (hasSurface) { - // The activity was paused but not stopped, so the surface still - // exists. Therefore - // surfaceCreated() won't be called, so init the camera here. - initCamera(surfaceHolder); - } else { - // Install the callback and wait for surfaceCreated() to init the - // camera. - surfaceHolder.addCallback(this); - surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); - } - - } - - @Override - protected void onPause() { - super.onPause(); - if (handler != null) { - handler.quitSynchronously(); - handler = null; - } - cameraManager.closeDriver(); - } - - public void surfaceCreated(SurfaceHolder holder) { - if (!hasSurface) { - hasSurface = true; - initCamera(holder); - } - } - - public void surfaceDestroyed(SurfaceHolder holder) { - hasSurface = false; - } - - public void surfaceChanged(SurfaceHolder holder, int format, int width, - int height) { - - } - - private void initCamera(SurfaceHolder surfaceHolder) { - try { - - - cameraManager.openDriver(surfaceHolder); - // Creating the handler starts the preview, which can also throw a - // RuntimeException. - if (handler == null) { - //decodeFormats.addAll(DecodeFormatManager.ONE_D_FORMATS); - handler = new CaptureActivityHandler(this, decodeFormats, - characterSet, cameraManager); - } - } catch (IOException ioe) { - Log.w(TAG, ioe); - displayFrameworkBugMessageAndExit("IOException"); - } catch (RuntimeException e) { - // Barcode Scanner has seen crashes in the wild of this variety: - // java.?lang.?RuntimeException: Fail to connect to camera service - Log.w(TAG, "Unexpected error initializating camera", e); - displayFrameworkBugMessageAndExit("RuntimeException"); - } - } - - public Handler getHandler() { - return handler; - } - - ViewfinderView getViewfinderView() { - return viewfinderView; - } - - - private void displayFrameworkBugMessageAndExit(String info) { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(getString(R.string.ou_app_name)); - builder.setMessage("[" + info + "] " - + getString(R.string.msg_camera_framework_bug)); - builder.setPositiveButton(R.string.button_ok, new FinishListener(this)); - builder.setOnCancelListener(new FinishListener(this)); - builder.show(); - } - - public void drawViewfinder() { - // Draw image result - - viewfinderView.drawViewfinder(); - } - - public void removePoints() { - - } - - - /** - * A valid barcode has been found, so give an indication of success and show the results. - * - * @param rawResult The contents of the barcode. - * @param barcode A greyscale bitmap of the camera data which was decoded. - */ - public void handleDecode(Result rawResult, Bitmap barcode) { - - - /* - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setMessage("Code bar Message : " + rawResult.getText()) - .setCancelable(false) - .setPositiveButton("Yes", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - //restart preview to decode more barcodes - if(handler != null){ - handler.sendEmptyMessage(R.id.restart_preview); - } - } - }); - - AlertDialog alert = builder.create(); - alert.show(); - */ - - //Toast.makeText(this, rawResult.getText(), Toast.LENGTH_LONG).show(); - Log.d("BARCODE","Value"+ rawResult.getText()); - Intent intent = new Intent(); - intent.putExtra("barcodeValue", rawResult.getText()); - setResult(BARCODE_SEARCH, intent); - finish(); - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/CaptureActivityHandler.java b/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/CaptureActivityHandler.java deleted file mode 100755 index a594c2778d..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/CaptureActivityHandler.java +++ /dev/null @@ -1,125 +0,0 @@ - -package org.evergreen.android.barcodescan; - -import java.util.Vector; - -import org.evergreen.android.R; -import org.evergreen.android.barcodescan.camera.CameraManager; - -import android.app.Activity; -import android.content.Intent; -import android.graphics.Bitmap; -import android.net.Uri; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.util.Log; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.Result; - -/** - * This class handles all the messaging which comprises the state machine for capture. -@ - */ -public final class CaptureActivityHandler extends Handler { - - private static final String TAG = CaptureActivityHandler.class.getSimpleName(); - - private final CaptureActivity activity; - private final DecodeThread decodeThread; - private final CameraManager cameraManager; - private State state; - - private enum State { - PREVIEW, - SUCCESS, - DONE - } - - CaptureActivityHandler(CaptureActivity activity, Vector decodeFormats, - String characterSet,CameraManager cameraManager) { - this.activity = activity; - decodeThread = new DecodeThread(activity, decodeFormats, characterSet, - new ViewfinderResultPointCallback(activity.getViewfinderView()), cameraManager); - decodeThread.start(); - state = State.SUCCESS; - - // Start ourselves capturing previews and decoding. - this.cameraManager = cameraManager; - cameraManager.startPreview(); - restartPreviewAndDecode(); - if (state == State.PREVIEW) { - this.cameraManager.requestAutoFocus(this, R.id.auto_focus); - } - - } - @Override - public void handleMessage(Message message) { - if (message.what == R.id.auto_focus) {//Log.d(TAG, "Got auto-focus message"); - // When one auto focus pass finishes, start another. This is the closest thing to - - - } else if (message.what == R.id.decode_succeeded) { - Log.d(TAG, "Got decode succeeded message"); - state = State.SUCCESS; - - - Bundle bundle = message.getData(); - Bitmap barcode = bundle == null ? null : - (Bitmap) bundle.getParcelable(DecodeThread.BARCODE_BITMAP); - - activity.handleDecode((Result) message.obj, barcode); - - - } else if (message.what == R.id.restart_preview) { - restartPreviewAndDecode(); - - - } else if (message.what == R.id.decode_failed) {// We're decoding as fast as possible, so when one decode fails, start another. - state = State.PREVIEW; - cameraManager.requestPreviewFrame(decodeThread.getHandler(), R.id.decode); - activity.removePoints(); - - - } else if (message.what == R.id.return_scan_result) { - Log.d(TAG, "Got return scan result message"); - activity.setResult(Activity.RESULT_OK, (Intent) message.obj); - activity.finish(); - - } else if (message.what == R.id.launch_product_query) { - Log.d(TAG, "Got product query message"); - String url = (String) message.obj; - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); - activity.startActivity(intent); - - } - } - - public void quitSynchronously() { - state = State.DONE; - cameraManager.stopPreview(); - Message quit = Message.obtain(decodeThread.getHandler(), R.id.quit); - quit.sendToTarget(); - try { - decodeThread.join(); - } catch (InterruptedException e) { - // continue - } - - // Be absolutely sure we don't send any queued up messages - removeMessages(R.id.decode_succeeded); - removeMessages(R.id.decode_failed); - } - - private void restartPreviewAndDecode() { - if (state == State.SUCCESS) { - state = State.PREVIEW; - cameraManager.requestPreviewFrame(decodeThread.getHandler(), R.id.decode); - cameraManager.requestAutoFocus(this, R.id.auto_focus); - activity.drawViewfinder(); - } - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/DecodeFormatManager.java b/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/DecodeFormatManager.java deleted file mode 100755 index f89f283032..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/DecodeFormatManager.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.evergreen.android.barcodescan; - -import java.util.Arrays; -import java.util.List; -import java.util.Vector; -import java.util.regex.Pattern; - -import android.content.Intent; -import android.net.Uri; -import com.google.zxing.BarcodeFormat; - -final class DecodeFormatManager { - - private static final Pattern COMMA_PATTERN = Pattern.compile(","); - - static final Vector PRODUCT_FORMATS; - static final Vector ONE_D_FORMATS; - static final Vector QR_CODE_FORMATS; - static final Vector DATA_MATRIX_FORMATS; - static { - PRODUCT_FORMATS = new Vector(5); - PRODUCT_FORMATS.add(BarcodeFormat.UPC_A); - PRODUCT_FORMATS.add(BarcodeFormat.UPC_E); - PRODUCT_FORMATS.add(BarcodeFormat.EAN_13); - PRODUCT_FORMATS.add(BarcodeFormat.EAN_8); - PRODUCT_FORMATS.add(BarcodeFormat.RSS_14); - ONE_D_FORMATS = new Vector(PRODUCT_FORMATS.size() + 4); - ONE_D_FORMATS.addAll(PRODUCT_FORMATS); - ONE_D_FORMATS.add(BarcodeFormat.CODE_39); - ONE_D_FORMATS.add(BarcodeFormat.CODE_93); - ONE_D_FORMATS.add(BarcodeFormat.CODE_128); - ONE_D_FORMATS.add(BarcodeFormat.ITF); - QR_CODE_FORMATS = new Vector(1); - QR_CODE_FORMATS.add(BarcodeFormat.QR_CODE); - DATA_MATRIX_FORMATS = new Vector(1); - DATA_MATRIX_FORMATS.add(BarcodeFormat.DATA_MATRIX); - } - - private DecodeFormatManager() {} - - static Vector parseDecodeFormats(Intent intent) { - List scanFormats = null; - String scanFormatsString = intent.getStringExtra(Intents.Scan.FORMATS); - if (scanFormatsString != null) { - scanFormats = Arrays.asList(COMMA_PATTERN.split(scanFormatsString)); - } - return parseDecodeFormats(scanFormats, intent.getStringExtra(Intents.Scan.MODE)); - } - - static Vector parseDecodeFormats(Uri inputUri) { - List formats = inputUri.getQueryParameters(Intents.Scan.FORMATS); - if (formats != null && formats.size() == 1 && formats.get(0) != null){ - formats = Arrays.asList(COMMA_PATTERN.split(formats.get(0))); - } - return parseDecodeFormats(formats, inputUri.getQueryParameter(Intents.Scan.MODE)); - } - - private static Vector parseDecodeFormats(Iterable scanFormats, - String decodeMode) { - if (scanFormats != null) { - Vector formats = new Vector(); - try { - for (String format : scanFormats) { - formats.add(BarcodeFormat.valueOf(format)); - } - return formats; - } catch (IllegalArgumentException iae) { - // ignore it then - } - } - if (decodeMode != null) { - if (Intents.Scan.PRODUCT_MODE.equals(decodeMode)) { - return PRODUCT_FORMATS; - } - if (Intents.Scan.QR_CODE_MODE.equals(decodeMode)) { - return QR_CODE_FORMATS; - } - if (Intents.Scan.DATA_MATRIX_MODE.equals(decodeMode)) { - return DATA_MATRIX_FORMATS; - } - if (Intents.Scan.ONE_D_MODE.equals(decodeMode)) { - return ONE_D_FORMATS; - } - } - return null; - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/DecodeHandler.java b/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/DecodeHandler.java deleted file mode 100755 index 9c49472cce..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/DecodeHandler.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.evergreen.android.barcodescan; - -import java.util.Hashtable; -import org.evergreen.android.R; -import org.evergreen.android.barcodescan.camera.CameraManager; - -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.util.Log; - -import com.google.zxing.BinaryBitmap; -import com.google.zxing.DecodeHintType; -import com.google.zxing.MultiFormatReader; -import com.google.zxing.ReaderException; -import com.google.zxing.Result; -import com.google.zxing.common.HybridBinarizer; - -final class DecodeHandler extends Handler { - - private static final String TAG = DecodeHandler.class.getSimpleName(); - - //Activity used for communication with her's handle - private final CaptureActivity activity; - private CameraManager cameraManager; - //Reader used to decode - private final MultiFormatReader multiFormatReader; - - //running state of this decode thread - private boolean running = true; - - DecodeHandler(CaptureActivity activity, Hashtable hints, CameraManager cameraManager) { - multiFormatReader = new MultiFormatReader(); - multiFormatReader.setHints(hints); - this.activity = activity; - this.cameraManager = cameraManager; - } - - /** - * Method handles messages obtained - * - */ - @Override - public void handleMessage(Message message) { - if (!running) { - return; - //if thread is not running do nothing - } - if (message.what == R.id.decode) { - decode((byte[]) message.obj, message.arg1, message.arg2); - - } else if (message.what == R.id.quit) {//quit, set running false - running = false; - Looper.myLooper().quit(); - - } - } - - - /** - * Decode the data within the viewfinder rectangle, and time how long it took. For efficiency, - * reuse the same reader objects from one decode to the next. - * - * @param data The YUV preview frame. - * @param width The width of the preview frame. - * @param height The height of the preview frame. - */ - private void decode(byte[] data, int width, int height) { - long start = System.currentTimeMillis(); - Result rawResult = null; - PlanarYUVLuminanceSource source = cameraManager.buildLuminanceSource(data, width, height); - if (source != null) { - BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); - try { - rawResult = multiFormatReader.decodeWithState(bitmap); - } catch (ReaderException re) { - // continue - } finally { - multiFormatReader.reset(); - } - } - - Handler handler = activity.getHandler(); - if (rawResult != null) { - // Don't log the barcode contents for security. - long end = System.currentTimeMillis(); - Log.d(TAG, "Found barcode in " + (end - start) + " ms"); - if (handler != null) { - Message message = Message.obtain(handler, R.id.decode_succeeded, rawResult); - Bundle bundle = new Bundle(); - bundle.putParcelable(DecodeThread.BARCODE_BITMAP, source.renderCroppedGreyscaleBitmap()); - message.setData(bundle); - message.sendToTarget(); - } - } else { - if (handler != null) { - Message message = Message.obtain(handler, R.id.decode_failed); - message.sendToTarget(); - } - } - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/DecodeThread.java b/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/DecodeThread.java deleted file mode 100755 index d48d3e7394..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/DecodeThread.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.evergreen.android.barcodescan; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.DecodeHintType; -import com.google.zxing.ResultPointCallback; - -import android.content.SharedPreferences; -import android.os.Handler; -import android.os.Looper; -import android.preference.PreferenceManager; - -import java.util.Hashtable; -import java.util.Vector; -import java.util.concurrent.CountDownLatch; - -import org.evergreen.android.barcodescan.camera.CameraManager; - -/** - * This thread does all the heavy lifting of decoding the images. - * - * @author dswitkin@google.com (Daniel Switkin) - */ -final class DecodeThread extends Thread { - - public static final String BARCODE_BITMAP = "barcode_bitmap"; - - private final CaptureActivity activity; - private final Hashtable hints; - private Handler handler; - private final CountDownLatch handlerInitLatch; - private CameraManager cameraManager; - DecodeThread(CaptureActivity activity, - Vector decodeFormats, - String characterSet, - ResultPointCallback resultPointCallback, CameraManager cameraManager) { - - this.activity = activity; - handlerInitLatch = new CountDownLatch(1); - this.cameraManager = cameraManager; - hints = new Hashtable(3); - - - - // The prefs can't change while the thread is running, so pick them up once here. - if (decodeFormats == null || decodeFormats.isEmpty()) { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity); - decodeFormats = new Vector(); - if (prefs.getBoolean(PreferencesActivity.KEY_DECODE_1D, true)) { - decodeFormats.addAll(DecodeFormatManager.ONE_D_FORMATS); - } - /* - if (prefs.getBoolean(PreferencesActivity.KEY_DECODE_QR, true)) { - decodeFormats.addAll(DecodeFormatManager.QR_CODE_FORMATS); - } - if (prefs.getBoolean(PreferencesActivity.KEY_DECODE_DATA_MATRIX, true)) { - decodeFormats.addAll(DecodeFormatManager.DATA_MATRIX_FORMATS); - } - */ - } - hints.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormats); - - if (characterSet != null) { - hints.put(DecodeHintType.CHARACTER_SET, characterSet); - } - hints.put(DecodeHintType.NEED_RESULT_POINT_CALLBACK, resultPointCallback); - } - - Handler getHandler() { - try { - handlerInitLatch.await(); - } catch (InterruptedException ie) { - // continue? - } - return handler; - } - - @Override - public void run() { - Looper.prepare(); - handler = new DecodeHandler(activity, hints, cameraManager); - handlerInitLatch.countDown(); - Looper.loop(); - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/FinishListener.java b/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/FinishListener.java deleted file mode 100755 index c184c1aa48..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/FinishListener.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.evergreen.android.barcodescan; - -import android.app.Activity; -import android.content.DialogInterface; - -/** - * Simple listener used to exit the app in a few cases. - * - * @author Sean Owen - */ -public final class FinishListener - implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener, Runnable { - - private final Activity activityToFinish; - - public FinishListener(Activity activityToFinish) { - this.activityToFinish = activityToFinish; - } - - public void onCancel(DialogInterface dialogInterface) { - run(); - } - - public void onClick(DialogInterface dialogInterface, int i) { - run(); - } - - public void run() { - activityToFinish.finish(); - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/Functions.java b/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/Functions.java deleted file mode 100755 index 57bee3eb15..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/Functions.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.evergreen.android.barcodescan; - -import android.content.Context; -import android.graphics.Color; -import android.widget.TextView; -import android.widget.Toast; - -/** - * - * @author George Oprina - * - * 08.06.2011 - */ - -public class Functions { - - // makes toast length short - public static void makeToast(String s, Context c) { - CharSequence text = s; - int duration = Toast.LENGTH_SHORT; - - Toast toast = Toast.makeText(c, text, duration); - toast.show(); - } - - // makes toast selectable length - public static void makeToast(String s, Context c, int length) { - CharSequence text = s; - int duration = Toast.LENGTH_SHORT; - - if (length == 1) - duration = Toast.LENGTH_LONG; - - Toast toast = Toast.makeText(c, text, duration); - toast.show(); - } - - // makes text view from string - public static TextView makeTextView(String s, Context c) { - TextView text = new TextView(c); - text.setBackgroundColor(Color.WHITE); - text.setText(s); - text.setTextColor(Color.BLACK); - return text; - } - - // thread sleep - public static void sleep(int msec) { - try { - Thread.sleep(msec); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/Intents.java b/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/Intents.java deleted file mode 100755 index f0edb4264f..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/Intents.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (C) 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.evergreen.android.barcodescan; - -/** - * This class provides the constants to use when sending an Intent to Barcode Scanner. - * These strings are effectively API and cannot be changed. - * - * @author dswitkin@google.com (Daniel Switkin) - */ -public final class Intents { - private Intents() { - } - - public static final class Scan { - /** - * Send this intent to open the Barcodes app in scanning mode, find a barcode, and return - * the results. - */ - public static final String ACTION = "com.google.zxing.client.android.SCAN"; - - /** - * By default, sending Scan.ACTION will decode all barcodes that we understand. However it - * may be useful to limit scanning to certain formats. Use Intent.putExtra(MODE, value) with - * one of the values below. - * - * Setting this is effectively shorthand for setting explicit formats with {@link #FORMATS}. - * It is overridden by that setting. - */ - public static final String MODE = "SCAN_MODE"; - - /** - * Decode only UPC and EAN barcodes. This is the right choice for shopping apps which get - * prices, reviews, etc. for products. - */ - public static final String PRODUCT_MODE = "PRODUCT_MODE"; - - /** - * Decode only 1D barcodes. - */ - public static final String ONE_D_MODE = "ONE_D_MODE"; - - /** - * Decode only QR codes. - */ - public static final String QR_CODE_MODE = "QR_CODE_MODE"; - - /** - * Decode only Data Matrix codes. - */ - public static final String DATA_MATRIX_MODE = "DATA_MATRIX_MODE"; - - /** - * Comma-separated list of formats to scan for. The values must match the names of - * {@link com.google.zxing.BarcodeFormat}s, e.g. {@link com.google.zxing.BarcodeFormat#EAN_13}. - * Example: "EAN_13,EAN_8,QR_CODE" - * - * This overrides {@link #MODE}. - */ - public static final String FORMATS = "SCAN_FORMATS"; - - /** - * @see com.google.zxing.DecodeHintType#CHARACTER_SET - */ - public static final String CHARACTER_SET = "CHARACTER_SET"; - - /** - * Optional parameters to specify the width and height of the scanning rectangle in pixels. - * The app will try to honor these, but will clamp them to the size of the preview frame. - * You should specify both or neither, and pass the size as an int. - */ - public static final String WIDTH = "SCAN_WIDTH"; - public static final String HEIGHT = "SCAN_HEIGHT"; - - /** - * If a barcode is found, Barcodes returns RESULT_OK to onActivityResult() of the app which - * requested the scan via startSubActivity(). The barcodes contents can be retrieved with - * intent.getStringExtra(RESULT). If the user presses Back, the result code will be - * RESULT_CANCELED. - */ - public static final String RESULT = "SCAN_RESULT"; - - /** - * Call intent.getStringExtra(RESULT_FORMAT) to determine which barcode format was found. - * See Contents.Format for possible values. - */ - public static final String RESULT_FORMAT = "SCAN_RESULT_FORMAT"; - - /** - * Call intent.getByteArrayExtra(RESULT_BYTES) to get a {@link byte[]} of raw bytes in the - * barcode, if available. - */ - public static final String RESULT_BYTES = "SCAN_RESULT_BYTES"; - - /** - * Setting this to false will not save scanned codes in the history. - */ - public static final String SAVE_HISTORY = "SAVE_HISTORY"; - - private Scan() { - } - } - - public static final class Encode { - /** - * Send this intent to encode a piece of data as a QR code and display it full screen, so - * that another person can scan the barcode from your screen. - */ - public static final String ACTION = "com.google.zxing.client.android.ENCODE"; - - /** - * The data to encode. Use Intent.putExtra(DATA, data) where data is either a String or a - * Bundle, depending on the type and format specified. Non-QR Code formats should - * just use a String here. For QR Code, see Contents for details. - */ - public static final String DATA = "ENCODE_DATA"; - - /** - * The type of data being supplied if the format is QR Code. Use - * Intent.putExtra(TYPE, type) with one of Contents.Type. - */ - public static final String TYPE = "ENCODE_TYPE"; - - /** - * The barcode format to be displayed. If this isn't specified or is blank, - * it defaults to QR Code. Use Intent.putExtra(FORMAT, format), where - * format is one of Contents.Format. - */ - public static final String FORMAT = "ENCODE_FORMAT"; - - private Encode() { - } - } - - public static final class SearchBookContents { - /** - * Use Google Book Search to search the contents of the book provided. - */ - public static final String ACTION = "com.google.zxing.client.android.SEARCH_BOOK_CONTENTS"; - - /** - * The book to search, identified by ISBN number. - */ - public static final String ISBN = "ISBN"; - - /** - * An optional field which is the text to search for. - */ - public static final String QUERY = "QUERY"; - - private SearchBookContents() { - } - } - - public static final class WifiConnect { - /** - * Internal intent used to trigger connection to a wi-fi network. - */ - public static final String ACTION = "com.google.zxing.client.android.WIFI_CONNECT"; - - /** - * The network to connect to, all the configuration provided here. - */ - public static final String SSID = "SSID"; - - /** - * The network to connect to, all the configuration provided here. - */ - public static final String TYPE = "TYPE"; - - /** - * The network to connect to, all the configuration provided here. - */ - public static final String PASSWORD = "PASSWORD"; - - private WifiConnect() { - } - } - - public static final class Share { - /** - * Give the user a choice of items to encode as a barcode, then render it as a QR Code and - * display onscreen for a friend to scan with their phone. - */ - public static final String ACTION = "com.google.zxing.client.android.SHARE"; - - private Share() { - } - } -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/PlanarYUVLuminanceSource.java b/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/PlanarYUVLuminanceSource.java deleted file mode 100755 index 86c9f8d33e..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/PlanarYUVLuminanceSource.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.evergreen.android.barcodescan; - -import com.google.zxing.LuminanceSource; - -import android.graphics.Bitmap; - -/** - * This object extends LuminanceSource around an array of YUV data returned from the camera driver, - * with the option to crop to a rectangle within the full data. This can be used to exclude - * superfluous pixels around the perimeter and speed up decoding. - * - * It works for any pixel format where the Y channel is planar and appears first, including - * YCbCr_420_SP and YCbCr_422_SP. - * - * @author dswitkin@google.com (Daniel Switkin) - */ -public final class PlanarYUVLuminanceSource extends LuminanceSource { - - private final byte[] yuvData; - private final int dataWidth; - private final int dataHeight; - private final int left; - private final int top; - - public PlanarYUVLuminanceSource(byte[] yuvData, int dataWidth, int dataHeight, int left, int top, - int width, int height, boolean reverseHorizontal) { - super(width, height); - - if (left + width > dataWidth || top + height > dataHeight) { - throw new IllegalArgumentException("Crop rectangle does not fit within image data."); - } - - this.yuvData = yuvData; - this.dataWidth = dataWidth; - this.dataHeight = dataHeight; - this.left = left; - this.top = top; - if (reverseHorizontal) { - reverseHorizontal(width, height); - } - } - - @Override - public byte[] getRow(int y, byte[] row) { - if (y < 0 || y >= getHeight()) { - throw new IllegalArgumentException("Requested row is outside the image: " + y); - } - int width = getWidth(); - if (row == null || row.length < width) { - row = new byte[width]; - } - int offset = (y + top) * dataWidth + left; - System.arraycopy(yuvData, offset, row, 0, width); - return row; - } - - @Override - public byte[] getMatrix() { - int width = getWidth(); - int height = getHeight(); - - // If the caller asks for the entire underlying image, save the copy and give them the - // original data. The docs specifically warn that result.length must be ignored. - if (width == dataWidth && height == dataHeight) { - return yuvData; - } - - int area = width * height; - byte[] matrix = new byte[area]; - int inputOffset = top * dataWidth + left; - - // If the width matches the full width of the underlying data, perform a single copy. - if (width == dataWidth) { - System.arraycopy(yuvData, inputOffset, matrix, 0, area); - return matrix; - } - - // Otherwise copy one cropped row at a time. - byte[] yuv = yuvData; - for (int y = 0; y < height; y++) { - int outputOffset = y * width; - System.arraycopy(yuv, inputOffset, matrix, outputOffset, width); - inputOffset += dataWidth; - } - return matrix; - } - - @Override - public boolean isCropSupported() { - return true; - } - - public Bitmap renderCroppedGreyscaleBitmap() { - int width = getWidth(); - int height = getHeight(); - int[] pixels = new int[width * height]; - byte[] yuv = yuvData; - int inputOffset = top * dataWidth + left; - - for (int y = 0; y < height; y++) { - int outputOffset = y * width; - for (int x = 0; x < width; x++) { - int grey = yuv[inputOffset + x] & 0xff; - pixels[outputOffset + x] = 0xFF000000 | (grey * 0x00010101); - } - inputOffset += dataWidth; - } - - Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - bitmap.setPixels(pixels, 0, width, 0, 0, width, height); - return bitmap; - } - - private void reverseHorizontal(int width, int height) { - byte[] yuvData = this.yuvData; - for (int y = 0, rowStart = top * dataWidth + left; y < height; y++, rowStart += dataWidth) { - int middle = rowStart + width / 2; - for (int x1 = rowStart, x2 = rowStart + width - 1; x1 < middle; x1++, x2--) { - byte temp = yuvData[x1]; - yuvData[x1] = yuvData[x2]; - yuvData[x2] = temp; - } - } - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/PreferencesActivity.java b/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/PreferencesActivity.java deleted file mode 100755 index 87527e6c9b..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/PreferencesActivity.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.evergreen.android.barcodescan; - -import android.content.SharedPreferences; -import android.content.SharedPreferences.OnSharedPreferenceChangeListener; -import android.os.Bundle; -import android.preference.CheckBoxPreference; -import android.preference.PreferenceActivity; -import android.preference.PreferenceScreen; - -import java.util.ArrayList; -import java.util.Collection; - -/** - * The main settings activity. - * - * @author dswitkin@google.com (Daniel Switkin) - */ -public final class PreferencesActivity extends PreferenceActivity - implements OnSharedPreferenceChangeListener { - - public static final String KEY_DECODE_1D = "preferences_decode_1D"; - public static final String KEY_DECODE_QR = "preferences_decode_QR"; - public static final String KEY_DECODE_DATA_MATRIX = "preferences_decode_Data_Matrix"; - public static final String KEY_CUSTOM_PRODUCT_SEARCH = "preferences_custom_product_search"; - - public static final String KEY_REVERSE_IMAGE = "preferences_reverse_image"; - public static final String KEY_PLAY_BEEP = "preferences_play_beep"; - public static final String KEY_VIBRATE = "preferences_vibrate"; - public static final String KEY_COPY_TO_CLIPBOARD = "preferences_copy_to_clipboard"; - public static final String KEY_FRONT_LIGHT = "preferences_front_light"; - public static final String KEY_BULK_MODE = "preferences_bulk_mode"; - public static final String KEY_REMEMBER_DUPLICATES = "preferences_remember_duplicates"; - public static final String KEY_SUPPLEMENTAL = "preferences_supplemental"; - - public static final String KEY_HELP_VERSION_SHOWN = "preferences_help_version_shown"; - public static final String KEY_NOT_OUR_RESULTS_SHOWN = "preferences_not_out_results_shown"; - - private CheckBoxPreference decode1D; - private CheckBoxPreference decodeQR; - private CheckBoxPreference decodeDataMatrix; - - @Override - protected void onCreate(Bundle icicle) { - super.onCreate(icicle); - // addPreferencesFromResource(R.xml.preferences); - - PreferenceScreen preferences = getPreferenceScreen(); - preferences.getSharedPreferences().registerOnSharedPreferenceChangeListener(this); - decode1D = (CheckBoxPreference) preferences.findPreference(KEY_DECODE_1D); - decodeQR = (CheckBoxPreference) preferences.findPreference(KEY_DECODE_QR); - decodeDataMatrix = (CheckBoxPreference) preferences.findPreference(KEY_DECODE_DATA_MATRIX); - disableLastCheckedPref(); - } - - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - disableLastCheckedPref(); - } - - private void disableLastCheckedPref() { - Collection checked = new ArrayList(3); - if (decode1D.isChecked()) { - checked.add(decode1D); - } - if (decodeQR.isChecked()) { - checked.add(decodeQR); - } - if (decodeDataMatrix.isChecked()) { - checked.add(decodeDataMatrix); - } - boolean disable = checked.size() < 2; - CheckBoxPreference[] checkBoxPreferences = {decode1D, decodeQR, decodeDataMatrix}; - for (CheckBoxPreference pref : checkBoxPreferences) { - pref.setEnabled(!(disable && checked.contains(pref))); - } - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/ViewfinderResultPointCallback.java b/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/ViewfinderResultPointCallback.java deleted file mode 100755 index e64dca3fcb..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/ViewfinderResultPointCallback.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.evergreen.android.barcodescan; - -import com.google.zxing.ResultPoint; -import com.google.zxing.ResultPointCallback; - -final class ViewfinderResultPointCallback implements ResultPointCallback { - - private final ViewfinderView viewfinderView; - - ViewfinderResultPointCallback(ViewfinderView viewfinderView) { - this.viewfinderView = viewfinderView; - } - - public void foundPossibleResultPoint(ResultPoint point) { - viewfinderView.addPossibleResultPoint(point); - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/ViewfinderView.java b/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/ViewfinderView.java deleted file mode 100755 index f51c7f13cc..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/ViewfinderView.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (C) 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.evergreen.android.barcodescan; - -import java.util.ArrayList; -import java.util.List; - -import org.evergreen.android.R; -import org.evergreen.android.barcodescan.camera.CameraManager; - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Rect; -import android.util.AttributeSet; -import android.view.View; - -import com.google.zxing.ResultPoint; - -/** - * This view is overlaid on top of the camera preview. It adds the viewfinder rectangle and partial - * transparency outside it, as well as the laser scanner animation and result points. - * - * @author dswitkin@google.com (Daniel Switkin) - */ -public final class ViewfinderView extends View { - - private static final int[] SCANNER_ALPHA = {0, 64, 128, 192, 255, 192, 128, 64}; - private static final long ANIMATION_DELAY = 80L; - private static final int CURRENT_POINT_OPACITY = 0xA0; - private static final int MAX_RESULT_POINTS = 20; - private static final int POINT_SIZE = 6; - - private CameraManager cameraManager; - private final Paint paint; - private Bitmap resultBitmap; - private int maskColor; - private int resultColor; - private int frameColor; - private int laserColor; - private int resultPointColor; - private int scannerAlpha; - private List possibleResultPoints; - private List lastPossibleResultPoints; - - // This constructor is used when the class is built from an XML resource. - public ViewfinderView(Context context, AttributeSet attrs) { - super(context, attrs); - - // Initialize these once for performance rather than calling them every time in onDraw(). - paint = new Paint(Paint.ANTI_ALIAS_FLAG); - Resources resources = getResources(); - maskColor = resources.getColor(R.color.viewfinder_mask); - resultColor = resources.getColor(R.color.result_view); - frameColor = resources.getColor(R.color.viewfinder_frame); - laserColor = resources.getColor(R.color.viewfinder_laser); - resultPointColor = resources.getColor(R.color.possible_result_points); - scannerAlpha = 0; - possibleResultPoints = new ArrayList(5); - lastPossibleResultPoints = null; - } - - public void setCameraManager(CameraManager cameraManager) { - this.cameraManager = cameraManager; - } - - - @Override - public void onDraw(Canvas canvas) { - Rect frame = cameraManager.getFramingRect(); - if (frame == null) { - return; - } - int width = canvas.getWidth(); - int height = canvas.getHeight(); - - // Draw the exterior (i.e. outside the framing rect) darkened - paint.setColor(resultBitmap != null ? resultColor : maskColor); - - canvas.drawRect(0, 0, width, frame.top, paint); - canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, paint); - canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1, paint); - canvas.drawRect(0, frame.bottom + 1, width, height, paint); - - if (resultBitmap != null) { - // Draw the opaque result bitmap over the scanning rectangle - paint.setAlpha(CURRENT_POINT_OPACITY); - canvas.drawBitmap(resultBitmap, null, frame, paint); - } else { - - // Draw a two pixel solid black border inside the framing rect - paint.setColor(frameColor); - canvas.drawRect(frame.left, frame.top, frame.right + 1, frame.top + 2, paint); - canvas.drawRect(frame.left, frame.top + 2, frame.left + 2, frame.bottom - 1, paint); - canvas.drawRect(frame.right - 1, frame.top, frame.right + 1, frame.bottom - 1, paint); - canvas.drawRect(frame.left, frame.bottom - 1, frame.right + 1, frame.bottom + 1, paint); - - // Draw a red "laser scanner" line through the middle to show decoding is active - paint.setColor(laserColor); - paint.setAlpha(SCANNER_ALPHA[scannerAlpha]); - scannerAlpha = (scannerAlpha + 1) % SCANNER_ALPHA.length; - int middle = frame.height() / 2 + frame.top; - canvas.drawRect(frame.left + 2, middle - 1, frame.right - 1, middle + 2, paint); - - Rect previewFrame = cameraManager.getFramingRectInPreview(); - float scaleX = frame.width() / (float) previewFrame.width(); - float scaleY = frame.height() / (float) previewFrame.height(); - - List currentPossible = possibleResultPoints; - List currentLast = lastPossibleResultPoints; - int frameLeft = frame.left; - int frameTop = frame.top; - if (currentPossible.isEmpty()) { - lastPossibleResultPoints = null; - } else { - possibleResultPoints = new ArrayList(5); - lastPossibleResultPoints = currentPossible; - paint.setAlpha(CURRENT_POINT_OPACITY); - paint.setColor(resultPointColor); - synchronized (currentPossible) { - for (ResultPoint point : currentPossible) { - canvas.drawCircle(frameLeft + (int) (point.getX() * scaleX), - frameTop + (int) (point.getY() * scaleY), - POINT_SIZE, paint); - } - } - } - if (currentLast != null) { - paint.setAlpha(CURRENT_POINT_OPACITY / 2); - paint.setColor(resultPointColor); - synchronized (currentLast) { - float radius = POINT_SIZE / 2.0f; - for (ResultPoint point : currentLast) { - canvas.drawCircle(frameLeft + (int) (point.getX() * scaleX), - frameTop + (int) (point.getY() * scaleY), - radius, paint); - } - } - } - - // Request another update at the animation interval, but only repaint the laser line, - // not the entire viewfinder mask. - postInvalidateDelayed(ANIMATION_DELAY, - frame.left - POINT_SIZE, - frame.top - POINT_SIZE, - frame.right + POINT_SIZE, - frame.bottom + POINT_SIZE); - } - } - - public void drawViewfinder() { - Bitmap resultBitmap = this.resultBitmap; - this.resultBitmap = null; - if (resultBitmap != null) { - resultBitmap.recycle(); - } - invalidate(); - } - - /** - * Draw a bitmap with the result points highlighted instead of the live scanning display. - * - * @param barcode An image of the decoded barcode. - */ - public void drawResultBitmap(Bitmap barcode) { - resultBitmap = barcode; - invalidate(); - } - - public void addPossibleResultPoint(ResultPoint point) { - List points = possibleResultPoints; - synchronized (points) { - points.add(point); - int size = points.size(); - if (size > MAX_RESULT_POINTS) { - // trim it - points.subList(0, size - MAX_RESULT_POINTS / 2).clear(); - } - } - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/camera/AutoFocusCallback.java b/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/camera/AutoFocusCallback.java deleted file mode 100755 index 3ad0a735ea..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/camera/AutoFocusCallback.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.evergreen.android.barcodescan.camera; - -import android.hardware.Camera; -import android.os.Handler; -import android.os.Message; -import android.util.Log; - -final class AutoFocusCallback implements Camera.AutoFocusCallback { - - private static final String TAG = AutoFocusCallback.class.getSimpleName(); - - private static final long AUTOFOCUS_INTERVAL_MS = 1500L; - - private Handler autoFocusHandler; - private int autoFocusMessage; - - void setHandler(Handler autoFocusHandler, int autoFocusMessage) { - this.autoFocusHandler = autoFocusHandler; - this.autoFocusMessage = autoFocusMessage; - } - - public void onAutoFocus(boolean success, Camera camera) { - if (autoFocusHandler != null) { - Message message = autoFocusHandler.obtainMessage(autoFocusMessage, success); - // Simulate continuous autofocus by sending a focus request every - // AUTOFOCUS_INTERVAL_MS milliseconds. - //Log.d(TAG, "Got auto-focus callback; requesting another"); - autoFocusHandler.sendMessageDelayed(message, AUTOFOCUS_INTERVAL_MS); - autoFocusHandler = null; - } else { - Log.d(TAG, "Got auto-focus callback, but no handler for it"); - } - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/camera/CameraConfigurationManager.java b/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/camera/CameraConfigurationManager.java deleted file mode 100755 index d2327b0b6e..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/camera/CameraConfigurationManager.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.evergreen.android.barcodescan.camera; - -import java.util.Collection; - -import org.evergreen.android.barcodescan.PreferencesActivity; - -import android.content.Context; -import android.content.SharedPreferences; -import android.graphics.Point; -import android.hardware.Camera; -import android.preference.PreferenceManager; -import android.util.Log; -import android.view.Display; -import android.view.WindowManager; - -/** - * A class which deals with reading, parsing, and setting the camera parameters which are used to - * configure the camera hardware. - */ -final class CameraConfigurationManager { - - private static final String TAG = "CameraConfiguration"; - private static final int MIN_PREVIEW_PIXELS = 320 * 240; // small screen - private static final int MAX_PREVIEW_PIXELS = 800 * 480; // large/HD screen - - private final Context context; - private Point screenResolution; - private Point cameraResolution; - - CameraConfigurationManager(Context context) { - this.context = context; - } - - /** - * Reads, one time, values from the camera that are needed by the app. - */ - void initFromCameraParameters(Camera camera) { - Camera.Parameters parameters = camera.getParameters(); - WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); - Display display = manager.getDefaultDisplay(); - int width = display.getWidth(); - int height = display.getHeight(); - // We're landscape-only, and have apparently seen issues with display thinking it's portrait - // when waking from sleep. If it's not landscape, assume it's mistaken and reverse them: - if (width < height) { - Log.i(TAG, "Display reports portrait orientation; assuming this is incorrect"); - int temp = width; - width = height; - height = temp; - } - screenResolution = new Point(width, height); - Log.i(TAG, "Screen resolution: " + screenResolution); - cameraResolution = findBestPreviewSizeValue(parameters, screenResolution, false); - Log.i(TAG, "Camera resolution: " + cameraResolution); - } - - void setDesiredCameraParameters(Camera camera) { - Camera.Parameters parameters = camera.getParameters(); - - if (parameters == null) { - Log.w(TAG, "Device error: no camera parameters are available. Proceeding without configuration."); - return; - } - - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - - initializeTorch(parameters, prefs); - String focusMode = findSettableValue(parameters.getSupportedFocusModes(), - Camera.Parameters.FOCUS_MODE_AUTO, - Camera.Parameters.FOCUS_MODE_MACRO); - if (focusMode != null) { - parameters.setFocusMode(focusMode); - } - - parameters.setPreviewSize(cameraResolution.x, cameraResolution.y); - camera.setParameters(parameters); - } - - Point getCameraResolution() { - return cameraResolution; - } - - Point getScreenResolution() { - return screenResolution; - } - - void setTorch(Camera camera, boolean newSetting) { - Camera.Parameters parameters = camera.getParameters(); - doSetTorch(parameters, newSetting); - camera.setParameters(parameters); - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - boolean currentSetting = prefs.getBoolean(PreferencesActivity.KEY_FRONT_LIGHT, false); - if (currentSetting != newSetting) { - SharedPreferences.Editor editor = prefs.edit(); - editor.putBoolean(PreferencesActivity.KEY_FRONT_LIGHT, newSetting); - editor.commit(); - } - } - - private static void initializeTorch(Camera.Parameters parameters, SharedPreferences prefs) { - boolean currentSetting = prefs.getBoolean(PreferencesActivity.KEY_FRONT_LIGHT, false); - doSetTorch(parameters, currentSetting); - } - - private static void doSetTorch(Camera.Parameters parameters, boolean newSetting) { - String flashMode; - if (newSetting) { - flashMode = findSettableValue(parameters.getSupportedFlashModes(), - Camera.Parameters.FLASH_MODE_TORCH, - Camera.Parameters.FLASH_MODE_ON); - } else { - flashMode = findSettableValue(parameters.getSupportedFlashModes(), - Camera.Parameters.FLASH_MODE_OFF); - } - if (flashMode != null) { - parameters.setFlashMode(flashMode); - } - } - - private static Point findBestPreviewSizeValue(Camera.Parameters parameters, - Point screenResolution, - boolean portrait) { - Point bestSize = null; - int diff = Integer.MAX_VALUE; - for (Camera.Size supportedPreviewSize : parameters.getSupportedPreviewSizes()) { - int pixels = supportedPreviewSize.height * supportedPreviewSize.width; - if (pixels < MIN_PREVIEW_PIXELS || pixels > MAX_PREVIEW_PIXELS) { - continue; - } - int supportedWidth = portrait ? supportedPreviewSize.height : supportedPreviewSize.width; - int supportedHeight = portrait ? supportedPreviewSize.width : supportedPreviewSize.height; - int newDiff = Math.abs(screenResolution.x * supportedHeight - supportedWidth * screenResolution.y); - if (newDiff == 0) { - bestSize = new Point(supportedWidth, supportedHeight); - break; - } - if (newDiff < diff) { - bestSize = new Point(supportedWidth, supportedHeight); - diff = newDiff; - } - } - if (bestSize == null) { - Camera.Size defaultSize = parameters.getPreviewSize(); - bestSize = new Point(defaultSize.width, defaultSize.height); - } - return bestSize; - } - - private static String findSettableValue(Collection supportedValues, - String... desiredValues) { - Log.i(TAG, "Supported values: " + supportedValues); - String result = null; - if (supportedValues != null) { - for (String desiredValue : desiredValues) { - if (supportedValues.contains(desiredValue)) { - result = desiredValue; - break; - } - } - } - Log.i(TAG, "Settable value: " + result); - return result; - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/camera/CameraManager.java b/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/camera/CameraManager.java deleted file mode 100755 index 60a442d725..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/camera/CameraManager.java +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (C) 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package org.evergreen.android.barcodescan.camera; - -import java.io.IOException; - -import org.evergreen.android.barcodescan.PlanarYUVLuminanceSource; -import org.evergreen.android.barcodescan.PreferencesActivity; - -import android.content.Context; -import android.content.SharedPreferences; -import android.graphics.Point; -import android.graphics.Rect; -import android.hardware.Camera; -import android.os.Handler; -import android.preference.PreferenceManager; -import android.util.Log; -import android.view.SurfaceHolder; - -/** - * This object wraps the Camera service object and expects to be the only one talking to it. The - * implementation encapsulates the steps needed to take preview-sized images, which are used for - * both preview and decoding. - * - * @author dswitkin@google.com (Daniel Switkin) - */ -public final class CameraManager { - - private static final String TAG = CameraManager.class.getSimpleName(); - - private static final int MIN_FRAME_WIDTH = 240; - private static final int MIN_FRAME_HEIGHT = 240; - private static final int MAX_FRAME_WIDTH = 600; - private static final int MAX_FRAME_HEIGHT = 400; - - private final Context context; - private final CameraConfigurationManager configManager; - private Camera camera; - private Rect framingRect; - private Rect framingRectInPreview; - private boolean initialized; - private boolean previewing; - private boolean reverseImage; - private int requestedFramingRectWidth; - private int requestedFramingRectHeight; - /** - * Preview frames are delivered here, which we pass on to the registered handler. Make sure to - * clear the handler so it will only receive one message. - */ - private final PreviewCallback previewCallback; - /** Autofocus callbacks arrive here, and are dispatched to the Handler which requested them. */ - private final AutoFocusCallback autoFocusCallback; - - public CameraManager(Context context) { - this.context = context; - this.configManager = new CameraConfigurationManager(context); - previewCallback = new PreviewCallback(configManager); - autoFocusCallback = new AutoFocusCallback(); - } - - /** - * Opens the camera driver and initializes the hardware parameters. - * - * @param holder The surface object which the camera will draw preview frames into. - * @throws IOException Indicates the camera driver failed to open. - */ - public void openDriver(SurfaceHolder holder) throws IOException { - Camera theCamera = camera; - if (theCamera == null) { - theCamera = Camera.open(); - if (theCamera == null) { - throw new IOException(); - } - camera = theCamera; - } - theCamera.setPreviewDisplay(holder); - - if (!initialized) { - initialized = true; - configManager.initFromCameraParameters(theCamera); - if (requestedFramingRectWidth > 0 && requestedFramingRectHeight > 0) { - setManualFramingRect(requestedFramingRectWidth, requestedFramingRectHeight); - requestedFramingRectWidth = 0; - requestedFramingRectHeight = 0; - } - } - configManager.setDesiredCameraParameters(theCamera); - - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - reverseImage = prefs.getBoolean(PreferencesActivity.KEY_REVERSE_IMAGE, false); - } - - /** - * Closes the camera driver if still in use. - */ - public void closeDriver() { - if (camera != null) { - camera.release(); - camera = null; - // Make sure to clear these each time we close the camera, so that any scanning rect - // requested by intent is forgotten. - framingRect = null; - framingRectInPreview = null; - } - } - - /** - * Asks the camera hardware to begin drawing preview frames to the screen. - */ - public void startPreview() { - Camera theCamera = camera; - if (theCamera != null && !previewing) { - theCamera.startPreview(); - previewing = true; - } - } - - /** - * Tells the camera to stop drawing preview frames. - */ - public void stopPreview() { - if (camera != null && previewing) { - camera.stopPreview(); - previewCallback.setHandler(null, 0); - autoFocusCallback.setHandler(null, 0); - previewing = false; - } - } - - /** - * A single preview frame will be returned to the handler supplied. The data will arrive as byte[] - * in the message.obj field, with width and height encoded as message.arg1 and message.arg2, - * respectively. - * - * @param handler The handler to send the message to. - * @param message The what field of the message to be sent. - */ - public void requestPreviewFrame(Handler handler, int message) { - Camera theCamera = camera; - if (theCamera != null && previewing) { - previewCallback.setHandler(handler, message); - theCamera.setOneShotPreviewCallback(previewCallback); - } - } - - /** - * Asks the camera hardware to perform an autofocus. - * - * @param handler The Handler to notify when the autofocus completes. - * @param message The message to deliver. - */ - public void requestAutoFocus(Handler handler, int message) { - if (camera != null && previewing) { - autoFocusCallback.setHandler(handler, message); - try { - camera.autoFocus(autoFocusCallback); - } catch (RuntimeException re) { - // Have heard RuntimeException reported in Android 4.0.x+; continue? - Log.w(TAG, "Unexpected exception while focusing", re); - } - } - } - - /** - * Calculates the framing rect which the UI should draw to show the user where to place the - * barcode. This target helps with alignment as well as forces the user to hold the device - * far enough away to ensure the image will be in focus. - * - * @return The rectangle to draw on screen in window coordinates. - */ - public Rect getFramingRect() { - if (framingRect == null) { - if (camera == null) { - return null; - } - Point screenResolution = configManager.getScreenResolution(); - int width = screenResolution.x * 3 / 4; - if (width < MIN_FRAME_WIDTH) { - width = MIN_FRAME_WIDTH; - } else if (width > MAX_FRAME_WIDTH) { - width = MAX_FRAME_WIDTH; - } - int height = screenResolution.y * 3 / 4; - if (height < MIN_FRAME_HEIGHT) { - height = MIN_FRAME_HEIGHT; - } else if (height > MAX_FRAME_HEIGHT) { - height = MAX_FRAME_HEIGHT; - } - int leftOffset = (screenResolution.x - width) / 2; - int topOffset = (screenResolution.y - height) / 2; - framingRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height); - Log.d(TAG, "Calculated framing rect: " + framingRect); - } - return framingRect; - } - - /** - * Like {@link #getFramingRect} but coordinates are in terms of the preview frame, - * not UI / screen. - */ - public Rect getFramingRectInPreview() { - if (framingRectInPreview == null) { - Rect framingRect = getFramingRect(); - if (framingRect == null) { - return null; - } - Rect rect = new Rect(framingRect); - Point cameraResolution = configManager.getCameraResolution(); - Point screenResolution = configManager.getScreenResolution(); - rect.left = rect.left * cameraResolution.x / screenResolution.x; - rect.right = rect.right * cameraResolution.x / screenResolution.x; - rect.top = rect.top * cameraResolution.y / screenResolution.y; - rect.bottom = rect.bottom * cameraResolution.y / screenResolution.y; - framingRectInPreview = rect; - } - return framingRectInPreview; - } - - /** - * Allows third party apps to specify the scanning rectangle dimensions, rather than determine - * them automatically based on screen resolution. - * - * @param width The width in pixels to scan. - * @param height The height in pixels to scan. - */ - public void setManualFramingRect(int width, int height) { - if (initialized) { - Point screenResolution = configManager.getScreenResolution(); - if (width > screenResolution.x) { - width = screenResolution.x; - } - if (height > screenResolution.y) { - height = screenResolution.y; - } - int leftOffset = (screenResolution.x - width) / 2; - int topOffset = (screenResolution.y - height) / 2; - framingRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height); - Log.d(TAG, "Calculated manual framing rect: " + framingRect); - framingRectInPreview = null; - } else { - requestedFramingRectWidth = width; - requestedFramingRectHeight = height; - } - } - - /** - * A factory method to build the appropriate LuminanceSource object based on the format - * of the preview buffers, as described by Camera.Parameters. - * - * @param data A preview frame. - * @param width The width of the image. - * @param height The height of the image. - * @return A PlanarYUVLuminanceSource instance. - */ - public PlanarYUVLuminanceSource buildLuminanceSource(byte[] data, int width, int height) { - Rect rect = getFramingRectInPreview(); - if (rect == null) { - return null; - } - // Go ahead and assume it's YUV rather than die. - return new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top, - rect.width(), rect.height(), reverseImage); - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/camera/FlashlightManager.java b/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/camera/FlashlightManager.java deleted file mode 100755 index 40393e9d6c..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/camera/FlashlightManager.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.evergreen.android.barcodescan.camera; - -import android.os.IBinder; -import android.util.Log; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -/** - * This class is used to activate the weak light on some camera phones (not flash) - * in order to illuminate surfaces for scanning. There is no official way to do this, - * but, classes which allow access to this function still exist on some devices. - * This therefore proceeds through a great deal of reflection. - * - * See http://almondmendoza.com/2009/01/05/changing-the-screen-brightness-programatically/ and - * http://code.google.com/p/droidled/source/browse/trunk/src/com/droidled/demo/DroidLED.java . - * Thanks to Ryan Alford for pointing out the availability of this class. - */ -final class FlashlightManager { - - private static final String TAG = FlashlightManager.class.getSimpleName(); - - private static final Object iHardwareService; - private static final Method setFlashEnabledMethod; - static { - iHardwareService = getHardwareService(); - setFlashEnabledMethod = getSetFlashEnabledMethod(iHardwareService); - if (iHardwareService == null) { - Log.v(TAG, "This device does supports control of a flashlight"); - } else { - Log.v(TAG, "This device does not support control of a flashlight"); - } - } - - private FlashlightManager() { - } - - private static Object getHardwareService() { - Class serviceManagerClass = maybeForName("android.os.ServiceManager"); - if (serviceManagerClass == null) { - return null; - } - - Method getServiceMethod = maybeGetMethod(serviceManagerClass, "getService", String.class); - if (getServiceMethod == null) { - return null; - } - - Object hardwareService = invoke(getServiceMethod, null, "hardware"); - if (hardwareService == null) { - return null; - } - - Class iHardwareServiceStubClass = maybeForName("android.os.IHardwareService$Stub"); - if (iHardwareServiceStubClass == null) { - return null; - } - - Method asInterfaceMethod = maybeGetMethod(iHardwareServiceStubClass, "asInterface", - IBinder.class); - if (asInterfaceMethod == null) { - return null; - } - - return invoke(asInterfaceMethod, null, hardwareService); - } - - private static Method getSetFlashEnabledMethod(Object iHardwareService) { - if (iHardwareService == null) { - return null; - } - Class proxyClass = iHardwareService.getClass(); - return maybeGetMethod(proxyClass, "setFlashlightEnabled", boolean.class); - } - - private static Class maybeForName(String name) { - try { - return Class.forName(name); - } catch (ClassNotFoundException cnfe) { - // OK - return null; - } catch (RuntimeException re) { - Log.w(TAG, "Unexpected error while finding class " + name, re); - return null; - } - } - - private static Method maybeGetMethod(Class clazz, String name, Class... argClasses) { - try { - return clazz.getMethod(name, argClasses); - } catch (NoSuchMethodException nsme) { - // OK - return null; - } catch (RuntimeException re) { - Log.w(TAG, "Unexpected error while finding method " + name, re); - return null; - } - } - - private static Object invoke(Method method, Object instance, Object... args) { - try { - return method.invoke(instance, args); - } catch (IllegalAccessException e) { - Log.w(TAG, "Unexpected error while invoking " + method, e); - return null; - } catch (InvocationTargetException e) { - Log.w(TAG, "Unexpected error while invoking " + method, e.getCause()); - return null; - } catch (RuntimeException re) { - Log.w(TAG, "Unexpected error while invoking " + method, re); - return null; - } - } - - static void enableFlashlight() { - setFlashlight(true); - } - - static void disableFlashlight() { - setFlashlight(false); - } - - private static void setFlashlight(boolean active) { - if (iHardwareService != null) { - invoke(setFlashEnabledMethod, iHardwareService, active); - } - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/camera/PreviewCallback.java b/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/camera/PreviewCallback.java deleted file mode 100755 index a371a990c9..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/camera/PreviewCallback.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.evergreen.android.barcodescan.camera; -/* - * Copyright (C) 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import android.graphics.Point; -import android.hardware.Camera; -import android.os.Handler; -import android.os.Message; -import android.util.Log; - -final class PreviewCallback implements Camera.PreviewCallback { - - private static final String TAG = PreviewCallback.class.getSimpleName(); - - private final CameraConfigurationManager configManager; - private Handler previewHandler; - private int previewMessage; - - PreviewCallback(CameraConfigurationManager configManager) { - this.configManager = configManager; - } - - void setHandler(Handler previewHandler, int previewMessage) { - this.previewHandler = previewHandler; - this.previewMessage = previewMessage; - } - - @Override - public void onPreviewFrame(byte[] data, Camera camera) { - Point cameraResolution = configManager.getCameraResolution(); - Handler thePreviewHandler = previewHandler; - if (thePreviewHandler != null) { - Message message = thePreviewHandler.obtainMessage(previewMessage, cameraResolution.x, - cameraResolution.y, data); - message.sendToTarget(); - previewHandler = null; - } else { - Log.d(TAG, "Got preview callback, but no handler for it"); - } - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/result/ResultHandler.java b/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/result/ResultHandler.java deleted file mode 100755 index ed8b3e6585..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/barcodescan/result/ResultHandler.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.evergreen.android.barcodescan.result; - -import com.google.zxing.Result; -import com.google.zxing.client.result.ParsedResult; -import com.google.zxing.client.result.ResultParser; - -import android.app.Activity; - -/** - * A base class for the Android-specific barcode handlers. These allow the app to polymorphically - * suggest the appropriate actions for each data type. - * - * This class also contains a bunch of utility methods to take common actions like opening a URL. - * They could easily be moved into a helper object, but it can't be static because the Activity - * instance is needed to launch an intent. - * - * @author dswitkin@google.com (Daniel Switkin) - */ -public class ResultHandler { - - private final ParsedResult result; - private final Activity activity; - private final Result rawResult; - - public ResultHandler(Activity activity, Result rawResult) { - this.activity = activity; - this.rawResult = rawResult; - result = parseResult(rawResult); - } - - - public ParsedResult getResult() { - return result; - } - - private static ParsedResult parseResult(Result rawResult) { - return ResultParser.parseResult(rawResult); - } - - /** - * Create a possibly styled string for the contents of the current barcode. - * - * @return The text to be displayed. - */ - public CharSequence getDisplayContents() { - String contents = result.getDisplayResult(); - return contents.replace("\r", ""); - } -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/database/DatabaseManager.java b/Open-ILS/src/Android/core/src/org/evergreen/android/database/DatabaseManager.java deleted file mode 100644 index b9a1461d01..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/database/DatabaseManager.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.database; - -import java.util.HashMap; -import java.util.logging.Logger; - -import org.androwrapee.db.DefaultDAO; -import org.androwrapee.db.DefaultDatabaseHelper; -import org.androwrapee.db.IllegalClassStructureException; -import org.androwrapee.db.ReflectionManager; -import org.evergreen.android.services.NotificationAlert; - -import android.content.Context; -import android.util.Log; - -/** - * The Class DatabaseDefaults. - */ -public class DatabaseManager { - - public static String TAG = "DatabaseManager"; - - /** The DATABASE NAME. */ - public static final String DATABASE_NAME = "evergreen.db"; - - /** The DATABASE VERSION. */ - public static final int DATABASE_VERSION = 1; - - /** The db helper. */ - private static DefaultDatabaseHelper dbHelper = null; - - /** The singleton reflection managers map. */ - @SuppressWarnings("rawtypes") - private static HashMap rmMap = new HashMap(); - - @SuppressWarnings("rawtypes") - private static HashMap daoMap = new HashMap(); - - /** - * Gets the Singleton database helper. - * - * @return the dB helper - */ - public static DefaultDatabaseHelper getDBHelper(Context context) { - if (dbHelper == null) - dbHelper = new DefaultDatabaseHelper(context, DATABASE_NAME, - DATABASE_VERSION, new Class[] { NotificationAlert.class }, - new String[] { NotificationAlert.tableName }); - return dbHelper; - } - - /** - * Gets a singleton instance of a reflection manager corresponding to a - * class. - * - * @param cls - * the class - * @return the reflection manager instance - */ - public static ReflectionManager getReflectionManagerInstance( - Class cls) { - if (rmMap.containsKey(cls)) - return rmMap.get(cls); - try { - ReflectionManager rm = new ReflectionManager(cls); - rmMap.put(cls, rm); - return rm; - } catch (IllegalClassStructureException ex) { - ex.printStackTrace(); - Log.d(TAG, - "Illegal Class Structure for class " + cls + ": " - + ex.getMessage()); - return null; - } - } - - /** - * Gets a singleton instance of a DefaultDAO object corresponding to a - * class. - * - * @param - * the generic type - * @param cls - * the class - * @param tableName - * the table name - * @return the DAO instance - */ - @SuppressWarnings("unchecked") - public static synchronized DefaultDAO getDAOInstance( - Context context, Class cls, String tableName) { - if (daoMap.containsKey(cls)) - return daoMap.get(cls); - DefaultDAO dao = new DefaultDAO(cls, - DatabaseManager.getDBHelper(context), - DatabaseManager.getReflectionManagerInstance(cls), tableName); - daoMap.put(cls, dao); - return dao; - } -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/globals/EvergreenConstants.java b/Open-ILS/src/Android/core/src/org/evergreen/android/globals/EvergreenConstants.java deleted file mode 100644 index c076ec99d3..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/globals/EvergreenConstants.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2013 Evergreen Open-ILS - * @author kenstir - */ -package org.evergreen.android.globals; - -/** - * Conversion of constants from Const.pm - */ -class EvergreenConstants { - - // Copy Statuses - public static final int COPY_STATUS_AVAILABLE = 0; - public static final int COPY_STATUS_CHECKED_OUT = 1; - public static final int COPY_STATUS_BINDERY = 2; - public static final int COPY_STATUS_LOST = 3; - public static final int COPY_STATUS_MISSING = 4; - public static final int COPY_STATUS_IN_PROCESS = 5; - public static final int COPY_STATUS_IN_TRANSIT = 6; - public static final int COPY_STATUS_RESHELVING = 7; - public static final int COPY_STATUS_ON_HOLDS_SHELF= 8; - public static final int COPY_STATUS_ON_ORDER = 9; - public static final int COPY_STATUS_ILL = 10; - public static final int COPY_STATUS_CATALOGING = 11; - public static final int COPY_STATUS_RESERVES = 12; - public static final int COPY_STATUS_DISCARD = 13; - public static final int COPY_STATUS_DAMAGED = 14; - public static final int COPY_STATUS_ON_RESV_SHELF = 15; - - // Circ defaults for pre-cataloged copies - public static final int PRECAT_COPY_FINE_LEVEL = 2; - public static final int PRECAT_COPY_LOAN_DURATION = 2; - public static final int PRECAT_CALL_NUMBER = -1; - public static final int PRECAT_RECORD = -1; - - // Circ constants - public static final int CIRC_DURATION_SHORT = 1; - public static final int CIRC_DURATION_NORMAL = 2; - public static final int CIRC_DURATION_EXTENDED = 3; - public static final int REC_FINE_LEVEL_LOW = 1; - public static final int REC_FINE_LEVEL_NORMAL = 2; - public static final int REC_FINE_LEVEL_HIGH = 3; - public static final String STOP_FINES_CHECKIN = "CHECKIN"; - public static final String STOP_FINES_RENEW = "RENEW"; - public static final String STOP_FINES_LOST = "LOST"; - public static final String STOP_FINES_CLAIMSRETURNED = "CLAIMSRETURNED"; - public static final String STOP_FINES_LONGOVERDUE = "LONGOVERDUE"; - public static final String STOP_FINES_MAX_FINES = "MAXFINES"; - public static final String STOP_FINES_CLAIMS_NEVERCHECKEDOUT = "CLAIMSNEVERCHECKEDOUT"; - public static final String UNLIMITED_CIRC_DURATION = "unlimited"; - - // Settings - public static final String SETTING_LOST_PROCESSING_FEE = "circ.lost_materials_processing_fee"; - public static final String SETTING_DEF_ITEM_PRICE = "cat.default_item_price"; - public static final String SETTING_ORG_BOUNCED_EMAIL = "org.bounced_emails"; - public static final String SETTING_CHARGE_LOST_ON_ZERO = "circ.charge_lost_on_zero"; - public static final String SETTING_VOID_OVERDUE_ON_LOST = "circ.void_overdue_on_lost"; - public static final String SETTING_HOLD_SOFT_STALL = "circ.hold_stalling.soft"; - public static final String SETTING_HOLD_HARD_STALL = "circ.hold_stalling.hard"; - public static final String SETTING_HOLD_SOFT_BOUNDARY = "circ.hold_boundary.soft"; - public static final String SETTING_HOLD_HARD_BOUNDARY = "circ.hold_boundary.hard"; - public static final String SETTING_HOLD_EXPIRE = "circ.hold_expire_interval"; - public static final String SETTING_HOLD_ESIMATE_WAIT_INTERVAL = "circ.holds.default_estimated_wait_interval"; - public static final String SETTING_VOID_LOST_ON_CHECKIN = "circ.void_lost_on_checkin"; - public static final String SETTING_MAX_ACCEPT_RETURN_OF_LOST = "circ.max_accept_return_of_lost"; - public static final String SETTING_VOID_LOST_PROCESS_FEE_ON_CHECKIN = "circ.void_lost_proc_fee_on_checkin"; - public static final String SETTING_RESTORE_OVERDUE_ON_LOST_RETURN = "circ.restore_overdue_on_lost_return"; - public static final String SETTING_LOST_IMMEDIATELY_AVAILABLE = "circ.lost_immediately_available"; - public static final String SETTING_BLOCK_HOLD_FOR_EXPIRED_PATRON = "circ.holds.expired_patron_block"; - public static final String SETTING_GENERATE_OVERDUE_ON_LOST_RETURN = "circ.lost.generate_overdue_on_checkin"; - - public static final String HOLD_TYPE_COPY = "C"; - public static final String HOLD_TYPE_FORCE = "F"; - public static final String HOLD_TYPE_RECALL = "R"; - public static final String HOLD_TYPE_ISSUANCE = "I"; - public static final String HOLD_TYPE_VOLUME = "V"; - public static final String HOLD_TYPE_TITLE = "T"; - public static final String HOLD_TYPE_METARECORD = "M"; - public static final String HOLD_TYPE_MONOPART = "P"; - - public static final String BILLING_TYPE_OVERDUE_MATERIALS = "Overdue materials"; - public static final String BILLING_TYPE_COLLECTION_FEE = "Long Overdue Collection Fee"; - public static final String BILLING_TYPE_DEPOSIT = "System: Deposit"; - public static final String BILLING_TYPE_RENTAL = "System: Rental"; - public static final String BILLING_NOTE_SYSTEM = "SYSTEM GENERATED"; - - public static final String ACQ_DEBIT_TYPE_PURCHASE = "purchase"; - public static final String ACQ_DEBIT_TYPE_TRANSFER = "xfer"; - - // all penalties with ID < 100 are managed automatically - public static final int PENALTY_AUTO_ID = 100; - public static final int PENALTY_PATRON_EXCEEDS_FINES = 1; - public static final int PENALTY_PATRON_EXCEEDS_OVERDUE_COUNT = 2; - public static final int PENALTY_INVALID_PATRON_ADDRESS = 29; - - public static final int BILLING_TYPE_NOTIFICATION_FEE = 9; -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/globals/GlobalConfigs.java b/Open-ILS/src/Android/core/src/org/evergreen/android/globals/GlobalConfigs.java deleted file mode 100644 index f05c02f198..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/globals/GlobalConfigs.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.globals; - -import android.content.Context; -import android.net.ConnectivityManager; -import android.util.Log; -import org.evergreen.android.accountAccess.AccountAccess; -import org.evergreen.android.accountAccess.SessionNotFoundException; -import org.evergreen.android.searchCatalog.Organisation; -import org.evergreen.android.searchCatalog.SearchCatalog; -import org.open_ils.idl.IDLParser; -import org.opensrf.util.JSONException; -import org.opensrf.util.JSONReader; - -import java.io.InputStream; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.*; - -public class GlobalConfigs { - - public static String IDL_FILE_FROM_ROOT = "/reports/fm_IDL.xml"; - public static String IDL_FILE_FROM_ASSETS = "fm_IDL.xml"; - public static String httpAddress = ""; - - private boolean init = false; - - private static String TAG = "GlobalConfigs"; - - private static boolean debugMode = true;//KCXXX make a developer preference - - public static boolean loadedIDL = false; - - public static boolean loadedOrgTree = false; - - public static String hold_icon_address = "/opac/images/tor/"; - - // two days notification before checkout expires, this can be modified from - // preferences - public static int NOTIFICATION_BEFORE_CHECKOUT_EXPIRATION = 2; - - // to parse date from requests - public static final String datePattern = "yyyy-MM-dd'T'hh:mm:ssZ"; - - /** The locale. */ - public String locale = "en-US"; - - private static GlobalConfigs globalConfigSingleton = null; - /** The organisations. */ - public ArrayList organisations; - - /** The collections request. */ - private String collectionsRequest = "/opac/common/js/" + locale - + "/OrgTree.js"; - - private GlobalConfigs(Context context) { - - initialize(context); - } - - public static GlobalConfigs getGlobalConfigs(Context context) { - - if (globalConfigSingleton == null) { - globalConfigSingleton = new GlobalConfigs(context); - } - - return globalConfigSingleton; - } - - /* - * Initialize function that retrieves IDL file and Orgs file - */ - private boolean initialize(Context context) { - if (!init) { - loadIDLFile(context); - getOrganisations(); - getCopyStatusesAvailable((ConnectivityManager) context - .getSystemService(Context.CONNECTIVITY_SERVICE)); - init = true; - return true; - } - return false; - } - - public static boolean isDebugMode() { - return debugMode; - } - - public static void setDebugMode(boolean debugMode) { - GlobalConfigs.debugMode = debugMode; - } - - public void loadIDLFile(Context context) { - - try { - Log.d(TAG, "loadIDLFile start"); - //@TODO maybe switch back to IDL_FILE_FROM_ROOT?class=circ&class=au&class=mvr&class=acp - InputStream in_IDL = context.getAssets().open(IDL_FILE_FROM_ASSETS); - IDLParser parser = new IDLParser(in_IDL); - parser.setKeepIDLObjects(false); - Log.d(TAG, "loadIDLFile parse"); - long start_ms = System.currentTimeMillis(); - parser.parse(); - long duration_ms = System.currentTimeMillis() - start_ms; - Log.d(TAG, "loadIDLFile parse took "+duration_ms+"ms"); - } catch (Exception e) { - Log.w(TAG, "Error in parsing IDL file", e); - } - - loadedIDL = true; - } - - /** - * Fetch the OrgTree.js file, and from it parse the list of organisations. - */ - public void getOrganisations() { - - String orgFile = null; - - organisations = new ArrayList(); - - try { - Log.d(TAG, "getOrg fetching "+httpAddress + collectionsRequest); - orgFile = Utils.getNetPageContent(httpAddress + collectionsRequest); - } catch (Exception e) { - } - - if (orgFile != null) { - long start_ms = System.currentTimeMillis(); - Log.d(TAG, "getOrg loading"); - organisations = new ArrayList(); - - // in case of wrong file - if (orgFile.indexOf("=") == -1) - return; - String orgArray = orgFile.substring(orgFile.indexOf("=") + 1, - orgFile.indexOf(";")); - Log.d(TAG, "getOrg array=" + orgArray.substring(0, orgArray.length()>50 ? 50 : -1)); - - // Parse javascript list - // Format: [[id, ou_type, parent_ou, name, opac_visible, shortname],...] - // Sample: [[149,3,146,"Agawam",0,"AGAWAM_MA"], - // [150,4,149,"Agawam Public Library",1,"AGAWAM"],...] - // ou_type can be treated as hierarchical nesting level - List orgList; - try { - orgList = new JSONReader(orgArray).readArray(); - } catch (JSONException e) { - Log.d(TAG, "getOrg failed parsing array", e); - return; - } - - // Convert json list into array of Organisation - for (int i=0; i() { - @Override - public int compare(Organisation a, Organisation b) { - if (a.parent == null) - return -1; // root is always first - return a.name.compareTo(b.name); - } - }); - /* - for (int i=0; i 0); - } - - public static void bookCoverImage(ImageView picture, String imageID, - int size) { - - String urlS = (GlobalConfigs.httpAddress - + "/opac/extras/ac/jacket/small/" + imageID); - - Bitmap bmp = null; // create a new Bitmap variable called bmp, and - // initialize it to null - - try { - - URL url = new URL(urlS); // create a URL object from the urlS string - // above - URLConnection conn = url.openConnection(); // save conn as a - // URLConnection - - conn.connect(); // connect to the URLConnection conn - InputStream is = conn.getInputStream(); // get the image from the - // URLConnection conn using - // InputStream is - BufferedInputStream bis = new BufferedInputStream(is, 8*1024); // create a - // BufferedInputStream - // called bis - // from is - bmp = BitmapFactory.decodeStream(bis); // use bis to convert the - // stream to a bitmap image, - // and save it to bmp - int bmpHeight = bmp.getHeight(); // stores the original height of - // the image - if (bmpHeight != 1) { - double scale = size / (double) bmpHeight; // sets the scaling - // number to match the - // desired size - double bmpWidthh = (double) bmp.getWidth() * scale; // scales - // and - // stores - // the - // original - // width - // into the - // desired - // one - int bmpWidth = (int) bmpWidthh; // gets the width of the picture - // and saves it - bmp = Bitmap.createScaledBitmap(bmp, bmpWidth, size, true); // creates - // and - // stores - // a - // new - // bmp - // with - // desired - // dimensions - } - - } catch (MalformedURLException e) { // catch errors - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } catch (IllegalStateException e) { - e.printStackTrace(); - } - picture.setImageBitmap(bmp); // send the Bitmap image bmp to pic, and - // call the method to set the image. - - } - - public static String getResponseTextcode(Object response) { - String textcode = null; - try { - textcode = ((Map) response).get("textcode"); - } catch (Exception e) { - } - return textcode; - } - - public static Object doRequest(HttpConnection conn, String service, - String methodName, String authToken, - Object[] params) throws SessionNotFoundException { - - Method method = new Method(methodName); - - Log.d(TAG, "doRequest Method :" + methodName + ": token :"+authToken+":"); - for (int i = 0; i < params.length; i++) { - method.addParam(params[i]); - Log.d(TAG, "Param " + i + ":" + params[i]); - } - - // sync request - HttpRequest req = new GatewayRequest(conn, service, method).send(); - Object resp = null; - - try { - resp = req.recv(); - } catch (NullPointerException e) { - // I know it's bad form to catch NPE. But until I implement some kind of on-demand IDL parsing, - // this is what happens when the JSONReader tries to parse a response of an unregistered class. - // Crash if debugMode, fail if not. - Log.d(TAG, "NPE...unregistered type?", e); - if (GlobalConfigs.isDebugMode()) { - throw(e); - } - } - if (resp != null) { - Log.d(TAG, "Sync Response: " + resp); - Object response = (Object) resp; - - String textcode = getResponseTextcode(resp); - if (TextUtils.equals(textcode, "NO_SESSION")) { - Log.d(TAG, textcode); - throw new SessionNotFoundException(); - } - - return response; - } - return null; - - } - - // does not require authToken - public static Object doRequest(HttpConnection conn, String service, - String methodName, ConnectivityManager cm, Object[] params) { - - Method method = new Method(methodName); - - Log.d(TAG, "doRequest Method :" + methodName + ":"); - for (int i = 0; i < params.length; i++) { - method.addParam(params[i]); - Log.d(TAG, "Param " + i + ": " + params[i]); - } - - // sync request - HttpRequest req = new GatewayRequest(conn, service, method).send(); - Object resp; - - while ((resp = req.recv()) != null) { - Log.d(TAG, "Sync Response: " + resp); - Object response = (Object) resp; - - return response; - - } - return null; - - } - - // does not throw exception - // is fast than with checks for multiple method invocations like in search - public static Object doRequestSimple(HttpConnection conn, String service, - String methodName, Object[] params) { - - if (Looper.myLooper() == Looper.getMainLooper()) { - // running on UI thread! - throw new NullPointerException(); - } - - Method method = new Method(methodName); - Log.d(TAG, "doRequestSimple Method :" + methodName); - for (int i = 0; i < params.length; i++) { - method.addParam(params[i]); - Log.d(TAG, "Param " + i + ":" + params[i]); - } - - // sync request - HttpRequest req = new GatewayRequest(conn, service, method).send(); - Object resp; - - while ((resp = req.recv()) != null) { - Log.d(TAG, "Sync Response: " + resp); - Object response = (Object) resp; - - return response; - - } - return null; - } - - public static ShowSessionNotAvailableRunnable showSessionNotAvailableDialog( - Context context) { - - return new ShowSessionNotAvailableRunnable(context); - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/AdvancedSearchActivity.java b/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/AdvancedSearchActivity.java deleted file mode 100644 index d0f8236e16..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/AdvancedSearchActivity.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.searchCatalog; - -import java.util.StringTokenizer; - -import org.evergreen.android.R; -import org.evergreen.android.accountAccess.AccountAccess; -import org.evergreen.android.views.AccountScreenDashboard; -import org.evergreen.android.views.splashscreen.SplashActivity; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup.LayoutParams; -import android.widget.Button; -import android.widget.EditText; -import android.widget.LinearLayout; -import android.widget.Spinner; -import android.widget.TextView; - -public class AdvancedSearchActivity extends Activity { - - private final String TAG = AdvancedSearchActivity.class.getName(); - - private AccountAccess accountAccess = null; - - private Context context; - - private Button homeButton; - - private Button myAccountButton; - - private TextView headerTitle; - - private StringBuilder advancedSearchFormattedText; - - public static final int RESULT_ADVANCED_SEARCH = 10; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (!SplashActivity.isAppInitialized()) { - SplashActivity.restartApp(this); - return; - } - - setContentView(R.layout.advanced_search); - - advancedSearchFormattedText = new StringBuilder(); - - // header portion actions - myAccountButton = (Button) findViewById(R.id.my_account_button); - myAccountButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(getApplicationContext(), - AccountScreenDashboard.class); - startActivity(intent); - } - }); - - homeButton = (Button) findViewById(R.id.action_bar_home_button); - homeButton.setText(R.string.advanced_search); - homeButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(getApplicationContext(), - SearchCatalogListView.class); - startActivity(intent); - } - }); - // end header portion actions - - context = this; - - final LinearLayout layout = (LinearLayout) findViewById(R.id.advanced_search_filters); - - Button addFilter = (Button) findViewById(R.id.advanced_search_add_filter_button); - - final Spinner search_index = (Spinner) findViewById(R.id.advanced_spinner_index); - final Spinner search_option = (Spinner) findViewById(R.id.advanced_spinner_option); - final EditText search_filter_text = (EditText) findViewById(R.id.advanced_search_text); - - addFilter.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - - int searchOptionVal = search_option.getSelectedItemPosition(); - - String searchText = search_index.getSelectedItem().toString() - .toLowerCase() - + ": "; - - advancedSearchFormattedText.append(search_index - .getSelectedItem().toString().toLowerCase() - + ": "); - - switch (searchOptionVal) { - - case 0: { - // contains - advancedSearchFormattedText.append(search_filter_text - .getText().toString()); - searchText = searchText - + search_filter_text.getText().toString(); - } - break; - case 1: { - // excludes - - StringTokenizer str = new StringTokenizer( - search_filter_text.getText().toString()); - - while (str.hasMoreTokens()) { - String token = str.nextToken(" "); - advancedSearchFormattedText.append(" -" + token); - searchText = searchText + " -" + token; - } - - } - break; - case 2: { - // matches exactly - advancedSearchFormattedText.append(" \"" - + search_filter_text.getText().toString() + "\""); - searchText = searchText + " \"" - + search_filter_text.getText().toString() + "\""; - } - break; - - } - - TextView text = new TextView(context); - text.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, - LayoutParams.WRAP_CONTENT)); - text.setText(searchText); - layout.addView(text); - - } - }); - - Button cancel = (Button) findViewById(R.id.advanced_search_cancel); - - cancel.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - finish(); - } - }); - - Button search = (Button) findViewById(R.id.advanced_search_button); - - search.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - Intent returnIntent = new Intent(); - returnIntent.putExtra("advancedSearchText", - advancedSearchFormattedText.toString()); - setResult(RESULT_ADVANCED_SEARCH, returnIntent); - finish(); - } - }); - - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/CopyCountInformation.java b/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/CopyCountInformation.java deleted file mode 100644 index d16fdde7b3..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/CopyCountInformation.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.searchCatalog; - -import android.util.Log; - -import java.io.Serializable; -import java.util.Map; - -public class CopyCountInformation implements Serializable { - - private final String TAG = CopyCountInformation.class.getName(); - private static final long serialVersionUID = 12343248767867L; - public Integer org_id; - public Integer count; - public Integer available; - public Integer depth; - public Integer unshadow; - - public CopyCountInformation(Object map) { - - this.org_id = ((Map) map).get("org_unit"); - this.count = ((Map) map).get("count"); - this.available = ((Map) map).get("available"); - this.depth = ((Map) map).get("depth"); - this.unshadow = ((Map) map).get("unshadow"); - - Log.d(TAG, org_id + " " + available + " " + count); - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/CopyInformation.java b/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/CopyInformation.java deleted file mode 100644 index 4c5d8d95e4..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/CopyInformation.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.searchCatalog; - -import android.util.Log; - -import java.io.Serializable; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map.Entry; -import java.util.Set; - -public class CopyInformation implements Serializable { - - private static final long serialVersionUID = -7269334218707079463L; - - private final String TAG = CopyInformation.class.getName(); - - public Integer org_id = -1; - - public String call_number_sufix; - - public String copy_location; - - public HashMap statuses; - - // the hash from the request method - private HashMap hashValCopy; - - // global, it is initialized when orgTree and fm_ild is downloaded - - public static LinkedHashMap availableOrgStatuses; - - public LinkedHashMap statusInformation = null; - - public CopyInformation(List list) { - - org_id = Integer.parseInt((String) list.get(0)); - call_number_sufix = (String) list.get(2); - copy_location = (String) list.get(4); - - hashValCopy = (HashMap) list.get(5); - - statusInformation = new LinkedHashMap(); - - Set> set = availableOrgStatuses.entrySet(); - - Iterator> it = set.iterator(); - - while (it.hasNext()) { - Entry entry = it.next(); - - if (hashValCopy.containsKey(entry.getKey())) { - statusInformation.put(entry.getValue(), - hashValCopy.get(entry.getKey()) + ""); - Log.d(TAG, "Added " + entry.getKey() + " " - + entry.getValue() + " " - + hashValCopy.get(entry.getKey())); - } - } - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/ImageDownloader.java b/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/ImageDownloader.java deleted file mode 100644 index 0db23a35ee..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/ImageDownloader.java +++ /dev/null @@ -1,481 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.evergreen.android.searchCatalog; - -import java.io.FilterInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.lang.ref.SoftReference; -import java.lang.ref.WeakReference; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.concurrent.ConcurrentHashMap; - -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.DefaultHttpClient; -import org.evergreen.android.R; - -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Color; -import android.graphics.drawable.ColorDrawable; -import android.graphics.drawable.Drawable; -import android.net.http.AndroidHttpClient; -import android.os.AsyncTask; -import android.os.Handler; -import android.util.Log; -import android.widget.ImageView; - -/** - * This helper class download images from the Internet and binds those with the - * provided ImageView. - * - *

- * It requires the INTERNET permission, which should be added to your - * application's manifest file. - *

- * - * A local cache of downloaded images is maintained internally to improve - * performance. - */ -public class ImageDownloader { - private static final String LOG_TAG = "ImageDownloader"; - - public enum Mode { - NO_ASYNC_TASK, NO_DOWNLOADED_DRAWABLE, CORRECT - } - - private Mode mode = Mode.CORRECT; - - private int MIN_IMG_HEIGHT = 75; - - private int MIN_IMG_WIDTH = 30; - - private int bitmap_width; - private int bitmap_height; - private boolean scale; - - public ImageDownloader(int min_img_height) { - - MIN_IMG_HEIGHT = min_img_height; - } - - public ImageDownloader() { - - } - - public ImageDownloader(int w, int h, boolean scale) { - this.bitmap_height = h; - this.bitmap_width = w; - this.scale = scale; - MIN_IMG_HEIGHT = h; - } - - /** - * Download the specified image from the Internet and binds it to the - * provided ImageView. The binding is immediate if the image is found in the - * cache and will be done asynchronously otherwise. A null bitmap will be - * associated to the ImageView if an error occurs. - * - * @param url - * The URL of the image to download. - * @param imageView - * The ImageView to bind the downloaded image to. - */ - public void download(String url, ImageView imageView) { - resetPurgeTimer(); - Bitmap bitmap = getBitmapFromCache(url); - - if (bitmap == null) { - forceDownload(url, imageView); - } else { - cancelPotentialDownload(url, imageView); - imageView.setImageBitmap(bitmap); - } - } - - /* - * Same as download but the image is always downloaded and the cache is not - * used. Kept private at the moment as its interest is not clear. private - * void forceDownload(String url, ImageView view) { forceDownload(url, view, - * null); } - */ - - /** - * Same as download but the image is always downloaded and the cache is not - * used. Kept private at the moment as its interest is not clear. - */ - private void forceDownload(String url, ImageView imageView) { - // State sanity: url is guaranteed to never be null in - // DownloadedDrawable and cache keys. - if (url == null) { - imageView.setImageDrawable(null); - return; - } - - if (cancelPotentialDownload(url, imageView)) { - switch (mode) { - case NO_ASYNC_TASK: - Bitmap bitmap = downloadBitmap(url); - addBitmapToCache(url, bitmap); - imageView.setImageBitmap(bitmap); - break; - - case NO_DOWNLOADED_DRAWABLE: - imageView.setMinimumHeight(MIN_IMG_HEIGHT); - BitmapDownloaderTask task = new BitmapDownloaderTask(imageView); - task.execute(url); - break; - - case CORRECT: - task = new BitmapDownloaderTask(imageView); - DownloadedDrawable downloadedDrawable = new DownloadedDrawable( - task); - imageView.setImageDrawable(downloadedDrawable); - imageView.setMinimumHeight(MIN_IMG_HEIGHT); - imageView.setMinimumWidth(MIN_IMG_WIDTH); - task.execute(url); - break; - } - } - } - - /** - * Returns true if the current download has been canceled or if there was no - * download in progress on this image view. Returns false if the download in - * progress deals with the same url. The download is not stopped in that - * case. - */ - private static boolean cancelPotentialDownload(String url, - ImageView imageView) { - BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView); - - if (bitmapDownloaderTask != null) { - String bitmapUrl = bitmapDownloaderTask.url; - if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) { - bitmapDownloaderTask.cancel(true); - } else { - // The same URL is already being downloaded. - return false; - } - } - return true; - } - - /** - * @param imageView - * Any imageView - * @return Retrieve the currently active download task (if any) associated - * with this imageView. null if there is no such task. - */ - private static BitmapDownloaderTask getBitmapDownloaderTask( - ImageView imageView) { - if (imageView != null) { - Drawable drawable = imageView.getDrawable(); - if (drawable instanceof DownloadedDrawable) { - DownloadedDrawable downloadedDrawable = (DownloadedDrawable) drawable; - return downloadedDrawable.getBitmapDownloaderTask(); - } - } - return null; - } - - Bitmap downloadBitmap(String url) { - final int IO_BUFFER_SIZE = 4 * 1024; - - // AndroidHttpClient is not allowed to be used from the main thread - final HttpClient client = (mode == Mode.NO_ASYNC_TASK) ? new DefaultHttpClient() - : AndroidHttpClient.newInstance("Android"); - - HttpGet getRequest = null; - try { - getRequest = new HttpGet(url); - } catch (Exception e) { - if ((client instanceof AndroidHttpClient)) { - ((AndroidHttpClient) client).close(); - } - return null; - } - - try { - HttpResponse response = client.execute(getRequest); - final int statusCode = response.getStatusLine().getStatusCode(); - if (statusCode != HttpStatus.SC_OK) { - Log.w("ImageDownloader", "Error " + statusCode - + " while retrieving bitmap from " + url); - return null; - } - - final HttpEntity entity = response.getEntity(); - if (entity != null) { - InputStream inputStream = null; - try { - inputStream = entity.getContent(); - // return BitmapFactory.decodeStream(inputStream); - // Bug on slow connections, fixed in future release. - return BitmapFactory.decodeStream(new FlushedInputStream( - inputStream)); - } finally { - if (inputStream != null) { - inputStream.close(); - } - entity.consumeContent(); - } - } - } catch (IOException e) { - getRequest.abort(); - Log.w(LOG_TAG, "I/O error while retrieving bitmap from " + url, e); - } catch (IllegalStateException e) { - getRequest.abort(); - Log.w(LOG_TAG, "Incorrect URL: " + url); - } catch (Exception e) { - getRequest.abort(); - Log.w(LOG_TAG, "Error while retrieving bitmap from " + url, e); - } finally { - if ((client instanceof AndroidHttpClient)) { - ((AndroidHttpClient) client).close(); - } - } - return null; - } - - /* - * An InputStream that skips the exact number of bytes provided, unless it - * reaches EOF. - */ - static class FlushedInputStream extends FilterInputStream { - public FlushedInputStream(InputStream inputStream) { - super(inputStream); - } - - @Override - public long skip(long n) throws IOException { - long totalBytesSkipped = 0L; - while (totalBytesSkipped < n) { - long bytesSkipped = in.skip(n - totalBytesSkipped); - if (bytesSkipped == 0L) { - int b = read(); - if (b < 0) { - break; // we reached EOF - } else { - bytesSkipped = 1; // we read one byte - } - } - totalBytesSkipped += bytesSkipped; - } - return totalBytesSkipped; - } - } - - /** - * The actual AsyncTask that will asynchronously download the image. - */ - class BitmapDownloaderTask extends AsyncTask { - private String url; - private final WeakReference imageViewReference; - - public BitmapDownloaderTask(ImageView imageView) { - imageViewReference = new WeakReference(imageView); - } - - /** - * Actual download method. - */ - @Override - protected Bitmap doInBackground(String... params) { - url = params[0]; - return downloadBitmap(url); - } - - /** - * Once the image is downloaded, associates it to the imageView - */ - @Override - protected void onPostExecute(Bitmap bitmap) { - if (isCancelled()) { - bitmap = null; - } - - addBitmapToCache(url, bitmap); - - if (imageViewReference != null) { - ImageView imageView = imageViewReference.get(); - BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView); - // Change bitmap only if this process is still associated with - // it - // Or if we don't use any bitmap to task association - // (NO_DOWNLOADED_DRAWABLE mode) - if ((this == bitmapDownloaderTask) || (mode != Mode.CORRECT)) { - Bitmap newScaledBitmap = null; - if (bitmap != null && scale == true) { - newScaledBitmap = Bitmap.createScaledBitmap(bitmap, - bitmap_width, bitmap_height, true); - imageView.setImageBitmap(newScaledBitmap); - } else { - imageView.setImageBitmap(bitmap); - } - } - - if (bitmap == null) { - if (imageView != null) - imageView.setImageResource(R.drawable.no_image); - } - } - - } - } - - /** - * A fake Drawable that will be attached to the imageView while the download - * is in progress. - * - *

- * Contains a reference to the actual download task, so that a download task - * can be stopped if a new binding is required, and makes sure that only the - * last started download process can bind its result, independently of the - * download finish order. - *

- */ - static class DownloadedDrawable extends ColorDrawable { - private final WeakReference bitmapDownloaderTaskReference; - - public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) { - super(Color.BLACK); - - bitmapDownloaderTaskReference = new WeakReference( - bitmapDownloaderTask); - } - - public BitmapDownloaderTask getBitmapDownloaderTask() { - return bitmapDownloaderTaskReference.get(); - } - } - - public void setMode(Mode mode) { - this.mode = mode; - clearCache(); - } - - /* - * Cache-related fields and methods. - * - * We use a hard and a soft cache. A soft reference cache is too - * aggressively cleared by the Garbage Collector. - */ - - private static final int HARD_CACHE_CAPACITY = 20; - private static final int DELAY_BEFORE_PURGE = 10 * 1000; // in milliseconds - - // Hard cache, with a fixed maximum capacity and a life duration - private final HashMap sHardBitmapCache = new LinkedHashMap( - HARD_CACHE_CAPACITY / 2, 0.75f, true) { - @Override - protected boolean removeEldestEntry( - LinkedHashMap.Entry eldest) { - if (size() > HARD_CACHE_CAPACITY) { - // Entries push-out of hard reference cache are transferred to - // soft reference cache - sSoftBitmapCache.put(eldest.getKey(), - new SoftReference(eldest.getValue())); - return true; - } else - return false; - } - }; - - // Soft cache for bitmaps kicked out of hard cache - private final static ConcurrentHashMap> sSoftBitmapCache = new ConcurrentHashMap>( - HARD_CACHE_CAPACITY / 2); - - private final Handler purgeHandler = new Handler(); - - private final Runnable purger = new Runnable() { - public void run() { - clearCache(); - } - }; - - /** - * Adds this bitmap to the cache. - * - * @param bitmap - * The newly downloaded bitmap. - */ - private void addBitmapToCache(String url, Bitmap bitmap) { - if (bitmap != null) { - synchronized (sHardBitmapCache) { - sHardBitmapCache.put(url, bitmap); - } - } - } - - /** - * @param url - * The URL of the image that will be retrieved from the cache. - * @return The cached bitmap or null if it was not found. - */ - private Bitmap getBitmapFromCache(String url) { - // First try the hard reference cache - synchronized (sHardBitmapCache) { - final Bitmap bitmap = sHardBitmapCache.get(url); - if (bitmap != null) { - // Bitmap found in hard cache - // Move element to first position, so that it is removed last - sHardBitmapCache.remove(url); - sHardBitmapCache.put(url, bitmap); - return bitmap; - } - } - - // Then try the soft reference cache - SoftReference bitmapReference = sSoftBitmapCache.get(url); - if (bitmapReference != null) { - final Bitmap bitmap = bitmapReference.get(); - if (bitmap != null) { - // Bitmap found in soft cache - return bitmap; - } else { - // Soft reference has been Garbage Collected - sSoftBitmapCache.remove(url); - } - } - - return null; - } - - /** - * Clears the image cache used internally to improve performance. Note that - * for memory efficiency reasons, the cache will automatically be cleared - * after a certain inactivity delay. - */ - public void clearCache() { - sHardBitmapCache.clear(); - sSoftBitmapCache.clear(); - } - - /** - * Allow a new delay before the automatic cache clear is done. - */ - private void resetPurgeTimer() { - purgeHandler.removeCallbacks(purger); - purgeHandler.postDelayed(purger, DELAY_BEFORE_PURGE); - } -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/MoreCopyInformation.java b/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/MoreCopyInformation.java deleted file mode 100644 index e53d6dd905..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/MoreCopyInformation.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.searchCatalog; - -import java.util.Iterator; -import java.util.Set; -import java.util.Map.Entry; - -import org.evergreen.android.R; -import org.evergreen.android.globals.GlobalConfigs; -import org.evergreen.android.views.AccountScreenDashboard; -import org.evergreen.android.views.splashscreen.SplashActivity; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup.LayoutParams; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.LinearLayout; -import android.widget.TextView; - -public class MoreCopyInformation extends Activity { - - private Button homeButton; - - private Button myAccountButton; - - private TextView headerTitle; - - private Context context; - - private RecordInfo record; - - private GlobalConfigs gl; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (!SplashActivity.isAppInitialized()) { - SplashActivity.restartApp(this); - return; - } - - setContentView(R.layout.copy_information_more); - gl = GlobalConfigs.getGlobalConfigs(context); - context = this; - record = (RecordInfo) getIntent().getSerializableExtra("recordInfo"); - - // header portion actions - myAccountButton = (Button) findViewById(R.id.my_account_button); - myAccountButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(getApplicationContext(), - AccountScreenDashboard.class); - startActivity(intent); - } - }); - - homeButton = (Button) findViewById(R.id.action_bar_home_button); - homeButton.setText(R.string.copy_information_title); - homeButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(getApplicationContext(), - SearchCatalogListView.class); - startActivity(intent); - } - }); - // end header portion actions - - LayoutInflater inf = (LayoutInflater) context - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - - // insert into main view - LinearLayout insertPoint = (LinearLayout) findViewById(R.id.record_details_copy_information); - addCopyInfo(inf, insertPoint); - - } - - public void addCopyInfo(LayoutInflater inflater, LinearLayout insertPoint) { - - for (int i = 0; i < record.copyInformationList.size(); i++) { - - View copy_info_view = inflater.inflate(R.layout.copy_information, - null); - - // fill in any details dynamically here - TextView library = (TextView) copy_info_view - .findViewById(R.id.copy_information_library); - TextView call_number = (TextView) copy_info_view - .findViewById(R.id.copy_information_call_number); - TextView copy_location = (TextView) copy_info_view - .findViewById(R.id.copy_information_copy_location); - - library.setText(gl.getOrganizationName(record.copyInformationList - .get(i).org_id) + " "); - call_number - .setText(record.copyInformationList.get(i).call_number_sufix); - copy_location - .setText(record.copyInformationList.get(i).copy_location); - - // insert into main view - insertPoint.addView(copy_info_view, new ViewGroup.LayoutParams( - LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT)); - - LinearLayout copy_statuses = (LinearLayout) copy_info_view - .findViewById(R.id.copy_information_statuses); - - CopyInformation info = record.copyInformationList.get(i); - - Set> set = info.statusInformation.entrySet(); - - Iterator> it = set.iterator(); - - while (it.hasNext()) { - - Entry ent = it.next(); - TextView statusName = new TextView(context); - statusName.setText(ent.getKey() + " : " + ent.getValue()); - - copy_statuses.addView(statusName, new LayoutParams( - LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); - - } - - } - - } -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/Organisation.java b/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/Organisation.java deleted file mode 100644 index acbb0cd652..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/Organisation.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.searchCatalog; - -public class Organisation { - - public String name = null; - - public String shortName = null; - - public Integer id = null; - - public Integer level = null; - - public Integer parent = null; - - public Integer isVisible = null; - - public Integer hiddenDepth = null; - - // used for indent display - public String padding = ""; - - public Organisation() { - - } -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/RecordInfo.java b/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/RecordInfo.java deleted file mode 100644 index 7889187256..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/RecordInfo.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.searchCatalog; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import android.util.Log; -import org.opensrf.util.OSRFObject; - -public class RecordInfo implements Serializable { - - // {"title","author","doc_id","doc_type","pubdate","isbn","publisher","tcn","subject","type_of_resources","call_numbers","edition","online_loc","synopsis","physical_description","toc","copy_count","series","serials","foreign_copy_maps"}); - - private static final long serialVersionUID = 10123L; - - private final String TAG = RecordInfo.class.getName(); - - public String title = null; - - public String author = null; - - public String pubdate = null; - - public String isbn = null; - - public Integer doc_id = null; - - public String publisher = null; - - public String subject = null; - - public String doc_type = null; - - public String online_loc = null; - - public String synopsis = null; - - public String physical_description = null; - - public String series = null; - - // tcn field - public String image = null; - - public boolean dummy = false; - - public ArrayList copyCountListInfo = null; - - public List copyInformationList = null; - - public RecordInfo() { - this.title = "Test title"; - this.author = "Test author"; - this.pubdate = "Publication date"; - copyInformationList = new ArrayList(); - - // marks the fact that this is a record made from no info - this.dummy = true; - } - - public RecordInfo(OSRFObject info) { - copyInformationList = new ArrayList(); - try { - - this.title = info.getString("title"); - this.author = info.getString("author"); - this.pubdate = info.getString("pubdate"); - this.publisher = info.getString("publisher"); - this.doc_id = info.getInt("doc_id"); - this.image = info.getString("tcn"); - this.doc_type = info.getString("doc_type"); - } catch (Exception e) { - Log.d(TAG, "Exception basic info " + e.getMessage()); - } - ; - - try { - this.isbn = (String) info.get("isbn"); - } catch (Exception e) { - Log.d(TAG, "Exception isbn " + e.getMessage()); - } - ; - - try { - - Map subjectMap = (Map) info.get("subject"); - - this.subject = ""; - - int no = subjectMap.entrySet().size(); - int i = 0; - for (Entry entry : subjectMap.entrySet()) { - i++; - if (i < no) - this.subject += entry.getKey() + " \n"; - else - this.subject += entry.getKey(); - } - - } catch (Exception e) { - Log.d(TAG, "Exception subject " + e.getMessage()); - } - ; - try { - - this.online_loc = ((List) info.get("online_loc")).get(0).toString(); - - } catch (Exception e) { - Log.d(TAG, "Exception online_loc " + e.getMessage()); - } - ; - try { - this.physical_description = (String) info - .get("physical_description"); - } catch (Exception e) { - Log.d(TAG, "Exception physical_description " - + e.getMessage()); - } - ; - try { - this.series = ""; - List seriesList = (List) info.get("series"); - for (int i = 0; i < seriesList.size(); i++) - if (i < seriesList.size() - 1) - this.series += seriesList.get(i) + ", "; - else - this.series += seriesList.get(i); - } catch (Exception e) { - Log.d(TAG, "Exception series " + e.getMessage()); - } - ; - - } -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/SampleUnderlinesNoFade.java b/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/SampleUnderlinesNoFade.java deleted file mode 100644 index b15270a033..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/SampleUnderlinesNoFade.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.searchCatalog; - -import java.util.ArrayList; - -import org.evergreen.android.R; -import org.evergreen.android.utils.ui.BaseSampleActivity; -import org.evergreen.android.utils.ui.BasicDetailsFragment; -import org.evergreen.android.utils.ui.TestFragmentAdapter; -import org.evergreen.android.utils.ui.UnderlinePageIndicator; -import org.evergreen.android.views.AccountScreenDashboard; -import org.evergreen.android.views.splashscreen.SplashActivity; - -import android.app.ProgressDialog; -import android.content.Context; -import android.content.Intent; -import android.net.ConnectivityManager; -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.support.v4.view.ViewPager; -import android.view.KeyEvent; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; -import android.widget.TextView; - -public class SampleUnderlinesNoFade extends BaseSampleActivity { - - private ArrayList records; - - private Button myAccountButton; - - private Button homeButton; - - private TextView headerTitle; - - private SearchCatalog search; - - private ArrayList searchRecords; - - private Context context; - - private ProgressDialog progressDialog; - - private Runnable searchRunnableWithOffset; - - public static final int RETURN_DATA = 5; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (!SplashActivity.isAppInitialized()) { - SplashActivity.restartApp(this); - return; - } - - setContentView(R.layout.simple_underlines); - - search = SearchCatalog.getInstance((ConnectivityManager)getSystemService(CONNECTIVITY_SERVICE)); - - records = (ArrayList) getIntent().getSerializableExtra( - "recordList"); - - if (records.get(records.size() - 1).dummy == true) - records.remove(records.size() - 1); - - context = this; - - // header portion actions - homeButton = (Button) findViewById(R.id.action_bar_home_button); - myAccountButton = (Button) findViewById(R.id.my_account_button); - - myAccountButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(getApplicationContext(), - AccountScreenDashboard.class); - startActivity(intent); - } - }); - - homeButton.setText(R.string.search_details_title); - homeButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(getApplicationContext(), - SearchCatalogListView.class); - startActivity(intent); - } - }); - // end header portion actions - - int record_position = getIntent().getIntExtra("recordPosition", 0); - mAdapter = new SearchFragmentAdapter(getSupportFragmentManager()); - - mPager = (ViewPager) findViewById(R.id.pager); - mPager.setAdapter(mAdapter); - - mPager.setCurrentItem(record_position); - - UnderlinePageIndicator indicator = (UnderlinePageIndicator) findViewById(R.id.indicator); - indicator.setViewPager(mPager); - indicator.setFades(false); - mIndicator = indicator; - searchRunnableWithOffset = new Runnable() { - - @Override - public void run() { - - runOnUiThread(new Runnable() { - - @Override - public void run() { - progressDialog = ProgressDialog.show(context, null,getResources().getText(R.string.dialog_load_more_message)); - } - }); - - searchRecords = search.getSearchResults(search.searchText, records.size()); - - runOnUiThread(new Runnable() { - - @Override - public void run() { - // don't clear record list - // recordList.clear(); - if (searchRecords.size() > 0) { - - for (int j = 0; j < searchRecords - .size(); j++) - records.add(searchRecords.get(j)); - - // add extra record to display more - // option button - - } - progressDialog.dismiss(); - } - }); - - } - }; - - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_BACK) { - Intent intent = new Intent(); - intent.putExtra("recordList", records); - setResult(RETURN_DATA, intent); - finish(); - - return true; - } - return super.onKeyDown(keyCode, event); - } - - - class SearchFragmentAdapter extends TestFragmentAdapter { - public SearchFragmentAdapter(FragmentManager fm) { - super(fm); - } - - @Override - public Fragment getItem(int position) { - // position +1 for 1 - size values - - if(position == records.size() - 1 && records.size() < search.visible){ - Thread getSearchResults = new Thread(searchRunnableWithOffset); - getSearchResults.start(); - } - return BasicDetailsFragment.newInstance(records.get(position), - position + 1, search.visible); - - } - - @Override - public int getCount() { - return records.size(); - // return TabsView.CONTENT.length; - } - - } -} \ No newline at end of file diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/SearchCatalog.java b/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/SearchCatalog.java deleted file mode 100644 index f8fd9938e4..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/SearchCatalog.java +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.searchCatalog; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import org.evergreen.android.globals.GlobalConfigs; -import org.evergreen.android.globals.Utils; -import org.opensrf.Method; -import org.opensrf.net.http.GatewayRequest; -import org.opensrf.net.http.HttpConnection; -import org.opensrf.net.http.HttpRequest; -import org.opensrf.net.http.HttpRequestHandler; -import org.opensrf.util.OSRFObject; - -import android.net.ConnectivityManager; -import android.util.Log; - -/** - * The Class SearchCatalog. - */ -public class SearchCatalog { - - /** The SERVICE. */ - public static String SERVICE = "open-ils.search"; - - /** The METHO d_ multicas s_ search. */ - public static String METHOD_MULTICLASS_QUERY = "open-ils.search.biblio.multiclass.query"; - - /** The METHO d_ sli m_ retrive. */ - public static String METHOD_SLIM_RETRIVE = "open-ils.search.biblio.record.mods_slim.retrieve"; - - /** - * Method - * - * @param : no parameters - * @returns : returns array of ccs objects - */ - - public static String METHOD_COPY_STATUS_ALL = "open-ils.search.config.copy_status.retrieve.all"; - - /** - * Method that returns library where record with id is - * - * @param : record ID to get all libraries, or just book ID, Current Library - * ID, User ID - * @returns : - * [[["4","","CONCERTO 27","","Stacks",{"0":5}],["4","","PERFORM 27" - * ,"","Stacks",{"0":2}]]] "0":% is the available books [org_id, - * call_number_sufix, copy_location, status1:count, status2:count - * ..] - */ - public static String METHOD_COPY_LOCATION_COUNTS = "open-ils.search.biblio.copy_location_counts.summary.retrieve"; - - /** - * Get copy statuses like Available, Checked_out , in_progress and others, - * ccs OSRFObjects - */ - public static String METHOD_GET_COPY_STATUSES = "open-ils.search.config.copy_status.retrieve.all"; - - /** - * Get copy count information - * - * @param : org_unit_id, record_id, "" ? - * @returns: objects - * [{"transcendant":null,"count":35,"org_unit":1,"depth":0, - * "unshadow":35,"available":35}, - * {"transcendant":null,"count":14,"org_unit" - * :2,"depth":1,"unshadow" - * :14,"available":14},{"transcendant":null, - * "count":7,"org_unit":4,"depth":2,"unshadow":7,"available":7}] - */ - public static String METHOD_GET_COPY_COUNT = "open-ils.search.biblio.record.copy_count"; - - public static SearchCatalog searchCatalogSingleton = null; - /** The conn. */ - public HttpConnection conn; - - // TODO get statuses on load - // open-ils.search.config.copy_status.retrieve.all - - /** The TAG. */ - public String TAG = "SearchCatalog"; - - // the org on witch the searches will be made - /** The selected organization. */ - public Organisation selectedOrganization = null; - - public Integer offset; - - public Integer visible; - - public Integer searchLimit = 10; - - public String searchText = null; - - private ConnectivityManager cm; - - public static SearchCatalog getInstance(ConnectivityManager cm) { - - if (searchCatalogSingleton == null) { - searchCatalogSingleton = new SearchCatalog(cm); - } - - return searchCatalogSingleton; - } - - public static SearchCatalog getInstance() { - - return searchCatalogSingleton; - } - - /** - * Instantiates a new search catalog. - */ - private SearchCatalog(ConnectivityManager cm) { - super(); - - this.cm = cm; - - try { - // configure the connection - conn = new HttpConnection(GlobalConfigs.httpAddress - + "/osrf-gateway-v1"); - - } catch (Exception e) { - System.err.println("Exception in establishing connection " - + e.getMessage()); - } - // registering classes so no longer necessary to register object classes - // manually - - } - - /** - * Gets the search results - * - * @param searchWords - * the search words - * @return the search results - */ - public ArrayList getSearchResults(String searchWords, - Integer offset) { - - searchText = searchWords; - - ArrayList resultsRecordInfo = new ArrayList(); - - Method method = new Method(METHOD_MULTICLASS_QUERY); - - HashMap complexParm = new HashMap(); - - try { - //KCXXX I'm not too sure about this depth option - if (this.selectedOrganization != null) { - if (this.selectedOrganization.id != null) - complexParm.put("org_unit", this.selectedOrganization.id); - if (this.selectedOrganization.level != null) - complexParm.put("depth", - this.selectedOrganization.level - 1); - } - // TODO change here, multiple result per page - complexParm.put("limit", searchLimit); - - complexParm.put("offset", offset); - - /* - * complexParm.put("offset",0); complexParm.put("visibility_limit", - * 3000); complexParm.put("default_class","keyword"); - */ - - } catch (Exception e) { - Log.d(TAG, "Exception in JSON " + e.getMessage()); - } - - // do request and check for connectivity - Object resp = Utils.doRequest(conn, SERVICE, METHOD_MULTICLASS_QUERY, - cm, new Object[] { complexParm, searchWords, 1 }); - - ArrayList ids = new ArrayList(); - - Log.d(TAG, "Sync Response: " + resp); - if (resp == null) - return resultsRecordInfo; // search failed or server crashed - - Map response = (Map) resp; - - Log.d(TAG, " ids : " + response.get("ids") + " "); - - List> result_ids; - result_ids = (List>) response.get("ids"); - Log.d(TAG, "length:"+result_ids.size()); - - // sometimes count is an int ("count":0) and sometimes string ("count":"1103") - visible = Integer.parseInt(response.get("count").toString()); - - for (int i = 0; i < result_ids.size(); i++) { - ids.add(result_ids.get(i).get(0)); - } - - Log.d(TAG, "Ids " + ids); - - // request other info based on ids - - for (int i = 0; i < ids.size(); i++) { - - RecordInfo record = new RecordInfo( - getItemShortInfo(Integer.parseInt(ids.get(i)))); - // get copy information - resultsRecordInfo.add(record); - - record.copyCountListInfo = getCopyCount( - Integer.parseInt(ids.get(i)), this.selectedOrganization.id); - - // get copy count - List> list = (List>) getLocationCount( - Integer.parseInt(ids.get(i)), this.selectedOrganization.id, - this.selectedOrganization.level - 1); - - if (list != null) - for (int j = 0; j < list.size(); j++) { - CopyInformation copyInfo = new CopyInformation(list.get(j)); - - record.copyInformationList.add(copyInfo); - } - - Log.d(TAG, "Title " + record.title + " Author " - + record.author + " Pub date" + record.pubdate - + " Publisher" + record.publisher); - } - - return resultsRecordInfo; - } - - /** - * Gets the item short info. - * - * @param id - * the id - * @return the item short info - */ - private OSRFObject getItemShortInfo(Integer id) { - - Method method = new Method(METHOD_SLIM_RETRIVE); - - method.addParam(id); - - HttpRequest req = new GatewayRequest(conn, SERVICE, method).send(); - Object resp; - while ((resp = req.recv()) != null) { - Log.d(TAG, "Sync Response: " + resp); - return (OSRFObject) resp; - } - - return null; - } - - /** - * Search catalog. - * - * @param searchWords - * the search words - * @return the object - */ - public Object searchCatalog(String searchWords) { - - Object response = Utils.doRequest(conn, SERVICE, METHOD_SLIM_RETRIVE, - cm, new Object[] { "keyword", searchWords }); - - return response; - - } - - /** - * Search catalog. - * - * @param searchWords - * the search words - * @param requestHandler - * the request handler - */ - public void searchCatalog(String searchWords, - HttpRequestHandler requestHandler) { - - Method method = new Method(METHOD_SLIM_RETRIVE); - - method.addParam(searchWords); - - // sync test - HttpRequest req = new GatewayRequest(conn, SERVICE, method).send(); - req.sendAsync(requestHandler); - - } - - public Object getCopyStatuses() { - - List ccs_list = (List) Utils.doRequestSimple( - conn, SERVICE, METHOD_COPY_STATUS_ALL, new Object[] {}); - - CopyInformation.availableOrgStatuses = new LinkedHashMap(); - - if (ccs_list != null) { - for (int i = 0; i < ccs_list.size(); i++) { - OSRFObject ccs_obj = ccs_list.get(i); - if (ccs_obj.getString("opac_visible").equals("t")) { - CopyInformation.availableOrgStatuses.put( - ccs_obj.getInt("id") + "", - ccs_obj.getString("name")); - //Log.d(TAG, "Add status "+ccs_obj.getString("name")); - } - } - } - return ccs_list; - } - - public Object getLocationCount(Integer recordID, Integer orgID, - Integer orgDepth) { - - List list = (List) Utils.doRequestSimple(conn, SERVICE, - METHOD_COPY_LOCATION_COUNTS, new Object[] { recordID, orgID, - orgDepth }); - return list; - - } - - public ArrayList getRecordsInfo(ArrayList ids) { - - ArrayList recordInfoArray = new ArrayList(); - - for (int i = 0; i < ids.size(); i++) { - RecordInfo recordInfo = new RecordInfo(getItemShortInfo(ids.get(i))); - recordInfoArray.add(recordInfo); - } - - return recordInfoArray; - } - - /** - * Select organisation. - * - * @param org - * the organization on witch the searches will be made - */ - public void selectOrganisation(Organisation org) { - - Log.d(TAG, "Select search organisation " + (org.level - 1) + " " - + org.id); - this.selectedOrganization = org; - - } - - public ArrayList getCopyCount(Integer recordID, - Integer orgID) { - - List list = (List) Utils.doRequestSimple(conn, SERVICE, - METHOD_GET_COPY_COUNT, new Object[] { orgID, recordID, "" }); - - ArrayList copyInfoList = new ArrayList(); - - if (list == null) - return copyInfoList; - - for (int i = 0; i < list.size(); i++) { - - CopyCountInformation copyInfo = new CopyCountInformation( - list.get(i)); - copyInfoList.add(copyInfo); - } - - return copyInfoList; - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/SearchCatalogListView.java b/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/SearchCatalogListView.java deleted file mode 100644 index 1d0f5186f9..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/searchCatalog/SearchCatalogListView.java +++ /dev/null @@ -1,795 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.searchCatalog; - -import java.util.ArrayList; -import java.util.List; - -import org.evergreen.android.R; -import org.evergreen.android.R.layout; -import org.evergreen.android.accountAccess.AccountAccess; -import org.evergreen.android.accountAccess.SessionNotFoundException; -import org.evergreen.android.accountAccess.bookbags.BookBag; -import org.evergreen.android.accountAccess.holds.PlaceHold; -import org.evergreen.android.barcodescan.CaptureActivity; -import org.evergreen.android.globals.GlobalConfigs; -import org.evergreen.android.views.AccountScreenDashboard; -import org.evergreen.android.views.ApplicationPreferences; -import org.evergreen.android.views.splashscreen.SplashActivity; - -import android.app.Activity; -import android.app.AlertDialog; -import android.app.ProgressDialog; -import android.content.Context; -import android.content.Intent; -import android.net.ConnectivityManager; -import android.os.Bundle; -import android.util.Log; -import android.view.ContextMenu; -import android.view.ContextMenu.ContextMenuInfo; -import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.View.OnKeyListener; -import android.view.ViewGroup; -import android.view.inputmethod.EditorInfo; -import android.view.inputmethod.InputMethodManager; -import android.widget.AbsListView; -import android.widget.AbsListView.OnScrollListener; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.AdapterView.OnItemSelectedListener; -import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.EditText; -import android.widget.ImageButton; -import android.widget.ImageView; -import android.widget.ListView; -import android.widget.Spinner; -import android.widget.TextView; -import android.widget.Toast; - -public class SearchCatalogListView extends Activity { - - private final String TAG = SearchCatalogListView.class.getName(); - - private ArrayList recordList; - - private EditText searchText; - - private ImageButton searchButton; - - private SearchCatalog search; - - private ListView lv; - - private SearchArrayAdapter adapter; - - private Context context; - - private ProgressDialog progressDialog; - - private ArrayList searchResults; - - private Spinner choseOrganisation; - - private GlobalConfigs globalConfigs; - - private static final int PLACE_HOLD = 0; - - private static final int DETAILS = 1; - - private static final int BOOK_BAG = 2; - - private TextView searchResultsNumber; - - private ArrayList bookBags; - - private Integer bookbag_selected = -1; - - private final ImageDownloader imageDownloader = new ImageDownloader(); - - private Runnable searchForResultsRunnable = null; - - private View searchOptionsMenu = null; - - private Button advancedSearchButton = null; - - private Button libraryHoursButton = null; - - private Button preferenceButton = null; - - private Button barcodeScanButton = null; - - private Button homeButton = null; - - private Button myAccountButton = null; - - private String advancedSearchString = null; - - // marks when the fetching record thread is started - private boolean loadingElements = false; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (!SplashActivity.isAppInitialized()) { - SplashActivity.restartApp(this); - return; - } - - setContentView(R.layout.search_result_list); - setTitle(R.string.browse_catalog); - - myAccountButton = (Button) findViewById(R.id.my_account_button); - myAccountButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(getApplicationContext(), - AccountScreenDashboard.class); - startActivity(intent); - } - }); - - homeButton = (Button) findViewById(R.id.action_bar_home_button); - homeButton.setText(R.string.browse_catalog); - homeButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - searchOptionsMenu.setVisibility(View.VISIBLE); - searchResultsNumber.setVisibility(View.INVISIBLE); - } - }); - // end header portion actions - - advancedSearchButton = (Button) findViewById(R.id.menu_advanced_search_button); - advancedSearchButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - // show advanced view dialog - Intent advancedSearch = new Intent(context, - AdvancedSearchActivity.class); - startActivityForResult(advancedSearch, 2); - } - }); - // get bookbags - bookBags = AccountAccess.getAccountAccess().getBookbags(); - - libraryHoursButton = (Button) findViewById(R.id.library_hours_button); - libraryHoursButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - // TODO Auto-generated method stub - } - }); - - preferenceButton = (Button) findViewById(R.id.preference_button); - preferenceButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Intent intent = new Intent(getApplicationContext(), - ApplicationPreferences.class); - startActivity(intent); - } - }); - - barcodeScanButton = (Button) findViewById(R.id.barcode_scan_button); - barcodeScanButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - Intent barcodeScan = new Intent(getApplicationContext(), - CaptureActivity.class); - startActivityForResult(barcodeScan, 10); - } - }); - // singleton initialize necessary IDL and Org data - globalConfigs = GlobalConfigs.getGlobalConfigs(this); - - context = this; - search = SearchCatalog - .getInstance((ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE)); - - recordList = new ArrayList(); - - // Create a customized ArrayAdapter - adapter = new SearchArrayAdapter(getApplicationContext(), - R.layout.search_result_item, recordList); - - searchResultsNumber = (TextView) findViewById(R.id.search_result_number); - - // Get reference to ListView holder - lv = (ListView) this.findViewById(R.id.search_results_list); - - searchOptionsMenu = findViewById(R.id.search_preference_options); - - progressDialog = new ProgressDialog(context); - - // Set the ListView adapter - lv.setAdapter(adapter); - - searchResults = new ArrayList(); - - registerForContextMenu(lv); - - searchForResultsRunnable = new Runnable() { - - @Override - public void run() { - - final String text = searchText.getText().toString(); - if (text.length() < 1) - return; - - runOnUiThread(new Runnable() { - @Override - public void run() { - - InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); - imm.hideSoftInputFromWindow( - searchText.getWindowToken(), 0); - - searchOptionsMenu.setVisibility(View.GONE); - searchResultsNumber.setVisibility(View.VISIBLE); - - progressDialog = ProgressDialog.show( - context, - getResources().getText(R.string.dialog_please_wait), - getResources().getText( - R.string.dialog_fetching_data_message)); - } - }); - - searchResults = search.getSearchResults(text, 0); - - runOnUiThread(new Runnable() { - - @Override - public void run() { - - recordList.clear(); - - if (searchResults.size() > 0) { - - for (int j = 0; j < searchResults.size(); j++) - recordList.add(searchResults.get(j)); - - // add extra record to display more option button - /* - * if (search.visible > recordList.size()) { - * recordList.add(new RecordInfo()); - * searchResultsNumber.setText(+recordList.size() - - * 1 + " out of " + search.visible); } else - */ - } - searchResultsNumber.setText(+recordList.size() - + " out of " + search.visible); - - adapter.notifyDataSetChanged(); - progressDialog.dismiss(); - - } - }); - - } - }; - - lv.setOnItemClickListener(new OnItemClickListener() { - - @Override - public void onItemClick(AdapterView arg0, View arg1, - int position, long arg3) { - - RecordInfo info = (RecordInfo) lv.getItemAtPosition(position); - - if (info.dummy == true) { - // this is the more view item button - progressDialog = new ProgressDialog(context); - - progressDialog.setMessage("Fetching data"); - progressDialog.show(); - final String text = searchText.getText().toString(); - - Thread searchThreadwithOffset = new Thread(new Runnable() { - - @Override - public void run() { - - searchResults.clear(); - - searchResults = search.getSearchResults(text, - recordList.size()); - - runOnUiThread(new Runnable() { - - @Override - public void run() { - - // don't clear record list - // recordList.clear(); - if (searchResults.size() > 0) { - - // remove previous more button - recordList.remove(recordList.size() - 1); - - for (int j = 0; j < searchResults - .size(); j++) - recordList.add(searchResults.get(j)); - - // add extra record to display more - // option button - if (search.visible > recordList.size()) { - recordList.add(new RecordInfo()); - searchResultsNumber.setText(adapter - .getCount() - - 1 - + " out of " - + search.visible); - } else - searchResultsNumber.setText(adapter - .getCount() - + " out of " - + search.visible); - } else { - searchResultsNumber.setText(adapter - .getCount() - + " out of " - + search.visible); - } - adapter.notifyDataSetChanged(); - progressDialog.dismiss(); - } - }); - - } - }); - - searchThreadwithOffset.start(); - } else { - // start activity with book details - - Intent intent = new Intent(getBaseContext(), - SampleUnderlinesNoFade.class); - // serialize object and pass it to next activity - intent.putExtra("recordInfo", info); - intent.putExtra("orgID", search.selectedOrganization.id); - intent.putExtra("depth", (search.selectedOrganization.level - 1)); - intent.putExtra("recordList", recordList); - intent.putExtra("recordPosition", position); - startActivityForResult(intent, 10); - } - } - }); - - lv.setOnScrollListener(new OnScrollListener() { - - @Override - public void onScrollStateChanged(AbsListView view, int scrollState) { - // TODO Auto-generated method stub - - } - - @Override - public void onScroll(AbsListView view, int firstVisibleItem, - int visibleItemCount, int totalItemCount) { - - if (!loadingElements) { - - /* - Log.d(TAG, " Scroll adapter " + totalItemCount + " " - + visibleItemCount + " " + firstVisibleItem + " " - + adapter.getCount() + " " + search.visible); - */ - if (totalItemCount > 0 - && (((totalItemCount - visibleItemCount) <= (firstVisibleItem)) && adapter - .getCount() < search.visible)) { - loadingElements = true; - Log.d(TAG, "Load more data"); - progressDialog = new ProgressDialog(context); - - progressDialog.setMessage(getResources().getText( - R.string.dialog_load_more_message)); - progressDialog.show(); - - Thread searchThreadwithOffset = new Thread( - new Runnable() { - - @Override - public void run() { - - String text = searchText.getText() - .toString(); - searchResults.clear(); - - searchResults = search - .getSearchResults(text, - adapter.getCount()); - - runOnUiThread(new Runnable() { - - @Override - public void run() { - - // don't clear record list - // recordList.clear(); - Log.d(TAG, "Returned " - + searchResults.size() - + " elements from search"); - if (searchResults.size() > 0) { - - for (int j = 0; j < searchResults - .size(); j++) - recordList - .add(searchResults - .get(j)); - - } - - searchResultsNumber.setText(adapter - .getCount() - + " out of " - + search.visible); - - adapter.notifyDataSetChanged(); - progressDialog.dismiss(); - loadingElements = false; - } - }); - - } - }); - - searchThreadwithOffset.start(); - } - } - } - }); - - searchText = (EditText) findViewById(R.id.searchText); - - // enter key now is labeled "Search" on virtual keyboard - searchText.setImeActionLabel("Search", EditorInfo.IME_ACTION_SEARCH); - searchText.setImeOptions(EditorInfo.IME_ACTION_SEARCH); - - // enter key on virtual keyboard starts the search - searchText.setOnKeyListener(new OnKeyListener() { - public boolean onKey(View v, int keyCode, KeyEvent event) { - // If the event is a key-down event on the "enter" button - if ((event.getAction() == KeyEvent.ACTION_DOWN) - && ((keyCode == KeyEvent.KEYCODE_ENTER) || keyCode == EditorInfo.IME_ACTION_SEARCH)) { - // Perform action on key press - Thread searchThread = new Thread(searchForResultsRunnable); - searchThread.start(); - return true; - } - return false; - } - }); - - - searchButton = (ImageButton) findViewById(R.id.searchButton); - searchButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - Thread searchThread = new Thread(searchForResultsRunnable); - searchThread.start(); - } - }); - - int selectedPos = 0; - int homeLibrary = 0; - if (AccountAccess.getAccountAccess() != null) { - homeLibrary = AccountAccess.getAccountAccess().getHomeLibraryID(); - } - ArrayList list = new ArrayList(); - Log.d(TAG, "Org scanning ..."); - if (globalConfigs.organisations != null) { - for (int i = 0; i < globalConfigs.organisations.size(); i++) { - Organisation org = globalConfigs.organisations.get(i); - list.add(org.padding + org.name); - if (org.id == homeLibrary) - selectedPos = i; - } - } - Log.d(TAG, "Org scanning ...done"); - ArrayAdapter adapter = new ArrayAdapter(this, - layout.spinner_layout, list); - choseOrganisation = (Spinner) findViewById(R.id.chose_organisation); - choseOrganisation.setAdapter(adapter); - choseOrganisation.setSelection(selectedPos); - choseOrganisation - .setOnItemSelectedListener(new OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView arg0, View arg1, - int ID, long arg3) { - // select the specific organization - search.selectOrganisation(globalConfigs.organisations - .get(ID)); - } - - @Override - public void onNothingSelected(AdapterView arg0) { - - } - - }); - - } - - @Override - public void onCreateContextMenu(ContextMenu menu, View v, - ContextMenuInfo menuInfo) { - - Log.d(TAG, "context menu"); - if (v.getId() == R.id.search_results_list) { - - AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; - menu.setHeaderTitle("Options"); - - menu.add(Menu.NONE, DETAILS, 0, "Details"); - menu.add(Menu.NONE, PLACE_HOLD, 1, "Place Hold"); - menu.add(Menu.NONE, BOOK_BAG, 2, "Add to bookbag"); - - } - } - - @Override - public boolean onContextItemSelected(MenuItem item) { - AdapterView.AdapterContextMenuInfo menuArrayItem = (AdapterView.AdapterContextMenuInfo) item - .getMenuInfo(); - int menuItemIndex = item.getItemId(); - - final RecordInfo info = (RecordInfo) lv - .getItemAtPosition(menuArrayItem.position); - // start activity with book details - - switch (item.getItemId()) { - - case DETAILS: { - - Intent intent = new Intent(getBaseContext(), - SampleUnderlinesNoFade.class); - // serialize object and pass it to next activity - intent.putExtra("recordInfo", info); - intent.putExtra("orgID", search.selectedOrganization.id); - intent.putExtra("depth", (search.selectedOrganization.level - 1)); - - intent.putExtra("recordList", recordList); - // TODO put total number - intent.putExtra("recordPosition", menuArrayItem.position); - startActivity(intent); - } - break; - case PLACE_HOLD: { - - Intent intent = new Intent(getBaseContext(), PlaceHold.class); - - intent.putExtra("recordInfo", info); - - startActivity(intent); - } - break; - case BOOK_BAG: { - - if (bookBags.size() > 0) { - String array_spinner[] = new String[bookBags.size()]; - - for (int i = 0; i < array_spinner.length; i++) - array_spinner[i] = bookBags.get(i).name; - - AlertDialog.Builder builder; - - LayoutInflater inflater = (LayoutInflater) context - .getSystemService(LAYOUT_INFLATER_SERVICE); - View layout = inflater.inflate(R.layout.bookbag_spinner, null); - - Spinner s = (Spinner) layout.findViewById(R.id.bookbag_spinner); - - Button add = (Button) layout - .findViewById(R.id.add_to_bookbag_button); - ArrayAdapter adapter = new ArrayAdapter(context, - android.R.layout.simple_spinner_item, array_spinner); - - s.setAdapter(adapter); - builder = new AlertDialog.Builder(context); - builder.setView(layout); - final AlertDialog alertDialog = builder.create(); - - add.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - // TODO Auto-generated method stub - Thread addtoBookbag = new Thread(new Runnable() { - @Override - public void run() { - AccountAccess ac = AccountAccess - .getAccountAccess(); - try { - ac.addRecordToBookBag(info.doc_id, - bookBags.get(bookbag_selected).id); - } catch (SessionNotFoundException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - runOnUiThread(new Runnable() { - @Override - public void run() { - progressDialog.dismiss(); - alertDialog.dismiss(); - } - }); - - } - }); - progressDialog = ProgressDialog.show(context, - getResources().getText(R.string.dialog_please_wait), - "Adding to bookbag"); - addtoBookbag.start(); - - } - }); - alertDialog.show(); - - s.setOnItemSelectedListener(new OnItemSelectedListener() { - - @Override - public void onItemSelected(AdapterView arg0, View arg1, - int position, long arg3) { - bookbag_selected = position; - } - - @Override - public void onNothingSelected(AdapterView arg0) { - } - - }); - } else - Toast.makeText(context, "No bookbags", Toast.LENGTH_SHORT) - .show(); - } - break; - } - - return super.onContextItemSelected(item); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - - switch (resultCode) { - - case SampleUnderlinesNoFade.RETURN_DATA : { - - ArrayList records = (ArrayList)data.getSerializableExtra("recordList"); - - recordList.clear(); - for(int i=0;i { - - private static final String tag = "SearchArrayAdapter"; - private Context context; - private ImageView recordImage; - private TextView recordTitle; - private TextView recordAuthor; - private TextView recordPublisher; - - private List records = new ArrayList(); - - public SearchArrayAdapter(Context context, int textViewResourceId, - List objects) { - super(context, textViewResourceId, objects); - this.context = context; - this.records = objects; - } - - public int getCount() { - return this.records.size(); - } - - public RecordInfo getItem(int index) { - return this.records.get(index); - } - - public View getView(int position, View convertView, ViewGroup parent) { - View row = convertView; - - // Get item - RecordInfo record = getItem(position); - - // if it is the right type of view - if (row == null - || row.findViewById(R.id.search_record_title) == null) { - - Log.d(tag, "Starting XML Row Inflation ... "); - LayoutInflater inflater = (LayoutInflater) this - .getContext().getSystemService( - Context.LAYOUT_INFLATER_SERVICE); - row = inflater.inflate(R.layout.search_result_item, parent, - false); - Log.d(tag, "Successfully completed XML Row Inflation!"); - - } - - Log.d(TAG, "reord image value " + recordImage); - // Get reference to ImageView - recordImage = (ImageView) row - .findViewById(R.id.search_record_img); - String imageHref = GlobalConfigs.httpAddress - + "/opac/extras/ac/jacket/small/" + record.isbn; - // start async download of image - imageDownloader.download(imageHref, recordImage); - // Get reference to TextView - title - recordTitle = (TextView) row - .findViewById(R.id.search_record_title); - - // Get reference to TextView - author - recordAuthor = (TextView) row - .findViewById(R.id.search_record_author); - - // Get referance to TextView - record Publisher date+publisher - recordPublisher = (TextView) row - .findViewById(R.id.search_record_publishing); - - // set text - recordTitle.setText(record.title); - recordAuthor.setText(record.author); - recordPublisher - .setText(record.pubdate + " " + record.publisher); - - return row; - } - } -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/services/NotificationAlert.java b/Open-ILS/src/Android/core/src/org/evergreen/android/services/NotificationAlert.java deleted file mode 100644 index 3aaa2e7d1d..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/services/NotificationAlert.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.services; - -import java.util.Date; - -import org.androwrapee.db.DatabaseClass; -import org.androwrapee.db.DatabaseField; -import org.androwrapee.db.IdField; - -@DatabaseClass -public class NotificationAlert { - - public static final String tableName = "notifications"; - - public static final int NOTIFICATION_INTENT = 123456; - - @IdField - public long id; - - @DatabaseField - public int intent_val; - - @DatabaseField - public Date triggerDate; - - @DatabaseField - public String message; - - // required constructor for DAO - public NotificationAlert() { - - } - - public NotificationAlert(int id, int intent_val, Date triggerDate, - String message) { - - this.id = id; - this.intent_val = intent_val; - this.triggerDate = triggerDate; - this.message = message; - } - - @Override - public String toString() { - - return " Notification:[ id: " + id + "; intent_val: " + intent_val - + "; triggerDate : " + triggerDate + "; message: " + message - + "]"; - } -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/services/NotificationReceiver.java b/Open-ILS/src/Android/core/src/org/evergreen/android/services/NotificationReceiver.java deleted file mode 100644 index c4ada30fa5..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/services/NotificationReceiver.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.services; - -import org.evergreen.android.views.splashscreen.SplashActivity; - -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.util.Log; - -public class NotificationReceiver extends BroadcastReceiver { - - private final String TAG = NotificationReceiver.class.getName(); - public static final int NOTIFICATION_ID = 1; - - @Override - public void onReceive(Context context, Intent intent) { - - String ns = Context.NOTIFICATION_SERVICE; - NotificationManager mNotificationManager = (NotificationManager) context - .getSystemService(ns); - - String checkoutMessage = intent.getStringExtra("checkoutMesage"); - - Log.d(TAG, "Message " + checkoutMessage); - // send notification - - int icon = android.R.drawable.ic_dialog_alert; - CharSequence tickerText = "Checkout item due date"; - long when = System.currentTimeMillis(); - - Notification notification = new Notification(icon, tickerText, when); - - notification.defaults |= Notification.FLAG_AUTO_CANCEL; - - CharSequence contentTitle = "EG - checkout item due date"; - CharSequence contentText = checkoutMessage; - // start evergreen - Intent notificationIntent = new Intent(context, SplashActivity.class); - notificationIntent.putExtra("jump", "checkout_items"); - - PendingIntent contentIntent = PendingIntent.getActivity(context, 0, - notificationIntent, 0); - - notification.setLatestEventInfo(context, contentTitle, contentText, - contentIntent); - - mNotificationManager.notify(NOTIFICATION_ID, notification); - - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/services/PeriodicServiceBroadcastReceiver.java b/Open-ILS/src/Android/core/src/org/evergreen/android/services/PeriodicServiceBroadcastReceiver.java deleted file mode 100644 index a087466f91..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/services/PeriodicServiceBroadcastReceiver.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.services; - -import java.util.Calendar; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; -import android.preference.PreferenceManager; -import android.util.Log; - -public class PeriodicServiceBroadcastReceiver extends BroadcastReceiver { - - public static final int INTENT_ID = 123; - - @Override - public void onReceive(Context context, Intent intent) { - - // do update logic - boolean mustDoUpdate = false; - - SharedPreferences prefs = PreferenceManager - .getDefaultSharedPreferences(context); - - // determine if to use alerts or not - boolean use_notifications = prefs.getBoolean("notifications_enabled", - false); - - if (use_notifications) { - // if no updates have been made - Calendar current = Calendar.getInstance(); - Calendar lastUpdateTime = Calendar.getInstance(); - lastUpdateTime.setTimeInMillis(prefs.getLong("lastUpdateTime", 0)); - - lastUpdateTime.add(Calendar.DAY_OF_MONTH, - ScheduledIntentService.SCHEDULE_TIME_INTERVAL); - - // if the last update time + elapsed scheduled time < current - // time we must do an update - if (lastUpdateTime.compareTo(current) == -1) { - mustDoUpdate = true; - } - - Log.d("app", "Network connectivity change or alarm must do update " - + mustDoUpdate); - - ConnectivityManager connMgr = (ConnectivityManager) context - .getSystemService(Context.CONNECTIVITY_SERVICE); - - NetworkInfo networkInfo = connMgr.getActiveNetworkInfo(); - // if internet available - if (networkInfo != null && networkInfo.isConnected()) { - - if (mustDoUpdate == true) { - Intent intentService = new Intent(context, - ScheduledIntentService.class); - context.startService(intentService); - } - } - - } - - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/services/RebootReceiver.java b/Open-ILS/src/Android/core/src/org/evergreen/android/services/RebootReceiver.java deleted file mode 100644 index 1a873a949e..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/services/RebootReceiver.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.services; - -import java.util.Calendar; - -import android.app.Activity; -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.preference.PreferenceManager; -import android.widget.Toast; - -public class RebootReceiver extends BroadcastReceiver { - - @Override - public void onReceive(Context context, Intent arg1) { - // reinitialize notifications - - SharedPreferences sharedPreferences = PreferenceManager - .getDefaultSharedPreferences(context); - - if (sharedPreferences.getBoolean("notifications_enabled", false)) { - - Toast.makeText(context, "Set up notification updates", - Toast.LENGTH_SHORT).show(); - // if enabled register the update service to run once per day - // get a Calendar object with current time - Calendar cal = Calendar.getInstance(); - - Intent bRecvIntent = new Intent(context, - PeriodicServiceBroadcastReceiver.class); - bRecvIntent.setAction(ScheduledIntentService.ACTION); - // update the current intent if it exists - PendingIntent sender = PendingIntent.getBroadcast(context, - NotificationAlert.NOTIFICATION_INTENT - + PeriodicServiceBroadcastReceiver.INTENT_ID, - bRecvIntent, PendingIntent.FLAG_UPDATE_CURRENT); - - // Get the AlarmManager service - AlarmManager am = (AlarmManager) context - .getSystemService(Activity.ALARM_SERVICE); - am.setRepeating(AlarmManager.RTC, cal.getTimeInMillis(), - 10000 * ScheduledIntentService.SCHEDULE_TIME_INTERVAL, - sender); - } - - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/services/ScheduledIntentService.java b/Open-ILS/src/Android/core/src/org/evergreen/android/services/ScheduledIntentService.java deleted file mode 100644 index 1e63fa499f..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/services/ScheduledIntentService.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.services; - -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.List; - -import android.accounts.AccountManager; -import android.accounts.AccountManagerFuture; -import android.os.Bundle; -import org.androwrapee.db.DefaultDAO; -import org.evergreen.android.accountAccess.AccountAccess; -import org.evergreen.android.accountAccess.SessionNotFoundException; -import org.evergreen.android.accountAccess.checkout.CircRecord; -import org.evergreen.android.database.DatabaseManager; -import org.evergreen.android.globals.GlobalConfigs; -import org.evergreen.android.globals.Utils; -import org.evergreen_ils.auth.Const; -import org.open_ils.idl.IDLParser; - -import android.app.AlarmManager; -import android.app.IntentService; -import android.app.PendingIntent; -import android.content.Intent; -import android.content.SharedPreferences; -import android.preference.PreferenceManager; -import android.util.Log; - -public class ScheduledIntentService extends IntentService { - - public static Date lastUpdateServiceDate; - - public static String TAG = ScheduledIntentService.class.getName(); - - public static String ACTION = "org.evergreen_ils.updateservice"; - - // fire up once a day - public static int SCHEDULE_TIME_INTERVAL = 1; - - public ScheduledIntentService() { - super("EvergreenIntentService"); - } - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - Log.d(TAG, "Start service"); - - return super.onStartCommand(intent, flags, startId); - } - - //TODO: share some of this code with LoadingTask.doInBackground - //TODO: this code needs major work. I never saw it work so I don't - // feel bad about disabling it for now. - @Override - protected void onHandleIntent(Intent intent) { - - Date currentDate = new Date(System.currentTimeMillis()); - - Log.d(TAG, "Notifications service started"); - - /* - * Download the necessary IDL files for checkout items operations like - * au (for auth), circ, mvr and acp - */ - String idlFile = GlobalConfigs.IDL_FILE_FROM_ROOT - + "?class=circ&class=au&class=mvr&class=acp"; - try { - Log.d(TAG, "Load IDL start"); - InputStream in_IDL = Utils.getNetInputStream(GlobalConfigs.httpAddress + idlFile); - IDLParser parser = new IDLParser(in_IDL); - parser.setKeepIDLObjects(false); - parser.parse(); - } catch (Exception e) { - Log.w("Error in parsing IDL", e); - } - - /* - AccountAccess accountAccess = AccountAccess.getAccountAccess(GlobalConfigs.httpAddress); - Log.d(TAG, tag+"Signing in"); - AccountManager accountManager = AccountManager.get(this); - - // what needs to be done is - // 1. get last used account name - // 2. see if the account still exists - // 3. get an auth token for it - // 4. start an evergreen session - AccountManagerFuture future = accountManager.getAuthTokenByFeatures(Const.ACCOUNT_TYPE, Const.AUTHTOKEN_TYPE, null, mCallingActivity, null, null, null, null); - Bundle bnd = future.getResult(); - String auth_token = bnd.getString(AccountManager.KEY_AUTHTOKEN); - String account_name = bnd.getString(AccountManager.KEY_ACCOUNT_NAME); - Log.d(TAG, tag+"account_name="+account_name+" token="+auth_token); - - boolean auth = false; - if (auth) { - - SharedPreferences sharedPreferences = PreferenceManager - .getDefaultSharedPreferences(getApplicationContext()); - // int daysBeforeDueDate = - // sharedPreferences.getInt("notifications_days_before_expiration", - // 2); - // TODO - int daysBeforeDueDate = 2; - ArrayList circRecords = new ArrayList(); - - // get the circ records - try { - circRecords = accountAccess.getItemsCheckedOut(); - } catch (SessionNotFoundException e) { - // auth just earlier realized, not supose to happen - } - - DefaultDAO daoNotifications = DatabaseManager - .getDAOInstance(this, NotificationAlert.class, - NotificationAlert.tableName); - daoNotifications.open(); - - // Fetch all alarms from database - List alarms = daoNotifications.fetchAll(""); - - for (int i = 0; i < alarms.size(); i++) { - Log.d(TAG, "Notification " + alarms.get(i)); - } - for (int i = 0; i < circRecords.size(); i++) { - - CircRecord checkoutRecord = circRecords.get(i); - - Date dueDate = checkoutRecord.getDueDateObject(); - - Calendar notificationDate = Calendar.getInstance(); - notificationDate.setTime(dueDate); - - notificationDate.add(Calendar.DAY_OF_MONTH, -daysBeforeDueDate); - Log.d(TAG, - " notification time start " - + notificationDate.getTime() + " current date " - + currentDate + " date between " + currentDate); - - // if due date in the future - if (currentDate.compareTo(notificationDate.getTime()) >= 0) { - - // get a Calendar object with current time - Calendar cal = Calendar.getInstance(); - - cal.setTime(dueDate); - - // just for test - cal.add(Calendar.HOUR, 4); - cal.add(Calendar.MINUTE, 37); - - Log.d(TAG, "Set notification in " + cal.getTime()); - - NotificationAlert notifications = daoNotifications - .fetch(checkoutRecord.circ_id); - NotificationAlert newNotificationInf = new NotificationAlert( - checkoutRecord.circ_id, - NotificationAlert.NOTIFICATION_INTENT - + checkoutRecord.circ_id, cal.getTime(), - "Checkout " + checkoutRecord.getAuthor() - + " expires on " - + checkoutRecord.getDueDate()); - - if (notifications == null) { - daoNotifications.insert(newNotificationInf, false); - } else { - // update info in database - daoNotifications.update(newNotificationInf, - checkoutRecord.circ_id); - } - - Intent intentNotification = new Intent(this, - NotificationReceiver.class); - - Log.d(TAG, "Set due date alarm at" + cal.getTime() - + " for " + newNotificationInf.id + " intent_val: " - + newNotificationInf.intent_val); - - intentNotification.putExtra("checkoutMessage", - "The item " + checkoutRecord.getAuthor() - + " is about to expire on " - + checkoutRecord.getDueDate()); - // update the current intent if it exists - PendingIntent sender = PendingIntent.getBroadcast(this, - NotificationAlert.NOTIFICATION_INTENT - + checkoutRecord.circ_id, - intentNotification, - PendingIntent.FLAG_UPDATE_CURRENT); - - // Get the AlarmManager service - AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE); - am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), - sender); - } - } - daoNotifications.close(); - - lastUpdateServiceDate = currentDate; - SharedPreferences.Editor editor = sharedPreferences.edit(); - editor.putLong("lastUpdateTime", lastUpdateServiceDate.getTime()); - editor.commit(); - - Log.d(TAG, "set last service update date " + lastUpdateServiceDate); - } - */ - } -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/utils/ui/BaseSampleActivity.java b/Open-ILS/src/Android/core/src/org/evergreen/android/utils/ui/BaseSampleActivity.java deleted file mode 100644 index 72c5f843e6..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/utils/ui/BaseSampleActivity.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.utils.ui; - -import java.util.Random; - -import org.evergreen.android.R; - -import android.support.v4.app.FragmentActivity; -import android.support.v4.view.ViewPager; -import android.view.Menu; -import android.view.MenuItem; -import android.widget.Toast; - -public abstract class BaseSampleActivity extends FragmentActivity { - private static final Random RANDOM = new Random(); - - public TestFragmentAdapter mAdapter; - public ViewPager mPager; - public PageIndicator mIndicator; - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.menu, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - int i = item.getItemId(); - if (i == R.id.random) { - final int page = RANDOM.nextInt(mAdapter.getCount()); - Toast.makeText(this, "Changing to page " + page, Toast.LENGTH_SHORT); - mPager.setCurrentItem(page); - return true; - } else if (i == R.id.add_page) { - if (mAdapter.getCount() < 10) { - mIndicator.notifyDataSetChanged(); - } - return true; - } else if (i == R.id.remove_page) { - if (mAdapter.getCount() > 1) { - mIndicator.notifyDataSetChanged(); - } - return true; - } - return super.onOptionsItemSelected(item); - } -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/utils/ui/BasicDetailsFragment.java b/Open-ILS/src/Android/core/src/org/evergreen/android/utils/ui/BasicDetailsFragment.java deleted file mode 100644 index 4f2228b772..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/utils/ui/BasicDetailsFragment.java +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.utils.ui; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.Map.Entry; -import java.util.Set; - -import android.util.Log; -import org.evergreen.android.R; -import org.evergreen.android.accountAccess.AccountAccess; -import org.evergreen.android.accountAccess.SessionNotFoundException; -import org.evergreen.android.accountAccess.bookbags.BookBag; -import org.evergreen.android.accountAccess.holds.PlaceHold; -import org.evergreen.android.globals.GlobalConfigs; -import org.evergreen.android.searchCatalog.CopyInformation; -import org.evergreen.android.searchCatalog.ImageDownloader; -import org.evergreen.android.searchCatalog.MoreCopyInformation; -import org.evergreen.android.searchCatalog.RecordInfo; -import org.evergreen.android.searchCatalog.SearchCatalog; - -import android.app.Dialog; -import android.app.ProgressDialog; -import android.content.Intent; -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.view.ViewGroup.LayoutParams; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemSelectedListener; -import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.Spinner; -import android.widget.TextView; -import android.widget.Toast; - -public class BasicDetailsFragment extends Fragment { - - private final String TAG = BasicDetailsFragment.class.getName(); - - private RecordInfo record; - private Integer position; - private Integer total; - - private TextView record_header; - - private TextView titleTextView; - private TextView authorTextView; - private TextView publisherTextView; - - private TextView seriesTextView; - private TextView subjectTextView; - private TextView synopsisTextView; - private TextView isbnTextView; - - private TextView copyCountTestView; - - private Button placeHoldButton; - - private Button addToBookbagButton; - - private LinearLayout showMore; - - private SearchCatalog search = null; - - private GlobalConfigs gl; - - private ProgressDialog progressDialog; - - private Integer bookbag_selected; - - private Dialog dialog; - - private ArrayList bookBags; - - private final ImageDownloader imageDownloader = new ImageDownloader(); - - private ImageView recordImage; - // max display info - private int list_size = 3; - - public static BasicDetailsFragment newInstance(RecordInfo record, - Integer position, Integer total) { - BasicDetailsFragment fragment = new BasicDetailsFragment(); - fragment.setDetails(record, position, total); - - return fragment; - } - - private void setDetails(RecordInfo record, Integer position, - Integer total) { - - this.record = record; - this.position = position; - this.total = total; - } - - public BasicDetailsFragment() { - - search = SearchCatalog.getInstance(); - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (savedInstanceState != null) { - record = (RecordInfo) savedInstanceState - .getSerializable("recordInfo"); - this.position = savedInstanceState.getInt("position"); - this.total = savedInstanceState.getInt("total"); - } - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - - gl = GlobalConfigs.getGlobalConfigs(getActivity()); - - LinearLayout layout = (LinearLayout) inflater.inflate( - R.layout.record_details_basic_fragment, null); - - record_header = (TextView) layout.findViewById(R.id.record_header_text); - copyCountTestView = (TextView) layout - .findViewById(R.id.record_details_simple_copy_count); - showMore = (LinearLayout) layout - .findViewById(R.id.record_details_show_more); - titleTextView = (TextView) layout - .findViewById(R.id.record_details_simple_title); - authorTextView = (TextView) layout - .findViewById(R.id.record_details_simple_author); - publisherTextView = (TextView) layout - .findViewById(R.id.record_details_simple_publisher); - - seriesTextView = (TextView) layout - .findViewById(R.id.record_details_simple_series); - subjectTextView = (TextView) layout - .findViewById(R.id.record_details_simple_subject); - synopsisTextView = (TextView) layout - .findViewById(R.id.record_details_simple_synopsis); - isbnTextView = (TextView) layout - .findViewById(R.id.record_details_simple_isbn); - - recordImage = (ImageView) layout - .findViewById(R.id.record_details_simple_image); - - placeHoldButton = (Button) layout - .findViewById(R.id.simple_place_hold_button); - addToBookbagButton = (Button) layout - .findViewById(R.id.simple_add_to_bookbag_button); - - placeHoldButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - Intent intent = new Intent(getActivity() - .getApplicationContext(), PlaceHold.class); - intent.putExtra("recordInfo", record); - startActivity(intent); - } - }); - - String imageHref = GlobalConfigs.httpAddress - + "/opac/extras/ac/jacket/large/" + record.isbn; - - // start async download of image - imageDownloader.download(imageHref, recordImage); - - AccountAccess ac = AccountAccess.getAccountAccess(); - - bookBags = ac.getBookbags(); - String array_spinner[] = new String[bookBags.size()]; - - for (int i = 0; i < array_spinner.length; i++) - array_spinner[i] = bookBags.get(i).name; - - dialog = new Dialog(getActivity()); - dialog.setContentView(R.layout.bookbag_spinner); - dialog.setTitle("Choose bookbag"); - Spinner s = (Spinner) dialog.findViewById(R.id.bookbag_spinner); - - Button add = (Button) dialog.findViewById(R.id.add_to_bookbag_button); - ArrayAdapter adapter = new ArrayAdapter(getActivity() - .getApplicationContext(), android.R.layout.simple_spinner_item, - array_spinner); - s.setAdapter(adapter); - - add.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - // TODO Auto-generated method stub - Thread addtoBookbag = new Thread(new Runnable() { - @Override - public void run() { - AccountAccess ac = AccountAccess.getAccountAccess(); - try { - ac.addRecordToBookBag(record.doc_id, - ac.getBookbags().get(bookbag_selected).id); - } catch (SessionNotFoundException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - progressDialog.dismiss(); - dialog.dismiss(); - } - }); - - } - }); - progressDialog = ProgressDialog.show(getActivity(), - getResources().getText(R.string.dialog_please_wait), - "Adding to bookbag"); - addtoBookbag.start(); - - } - }); - s.setOnItemSelectedListener(new OnItemSelectedListener() { - - @Override - public void onItemSelected(AdapterView arg0, View arg1, - int position, long arg3) { - bookbag_selected = position; - } - - @Override - public void onNothingSelected(AdapterView arg0) { - } - - }); - - addToBookbagButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - - if (bookBags.size() > 0) - dialog.show(); - else - Toast.makeText(getActivity(), "No bookbags", - Toast.LENGTH_SHORT).show(); - } - - }); - } - }); - - record_header.setText(String.format(getString(R.string.record_of), position, total)); - - titleTextView.setText(record.title); - authorTextView.setText(record.author); - publisherTextView.setText(record.pubdate + " " + record.publisher); - - seriesTextView.setText(record.series); - subjectTextView.setText(record.subject); - synopsisTextView.setText(record.synopsis); - - isbnTextView.setText(record.isbn); - - int current_org = 0; - if (search != null) - current_org = search.selectedOrganization.id; - - Log.d(TAG, "Size " + record.copyCountListInfo.size()); - - for (int i = 0; i < record.copyCountListInfo.size(); i++) { - Log.d(TAG, current_org + " " - + record.copyCountListInfo.get(i).org_id + " " - + record.copyCountListInfo.get(i).count); - if (record.copyCountListInfo.get(i).org_id == current_org) { - int total = record.copyCountListInfo.get(i).count; - int available = record.copyCountListInfo.get(i).available; - copyCountTestView.setText(available + " / " + total); - break; - } - } - - final LayoutInflater inf = inflater; - final LinearLayout lay = layout; - - // add more details - showMore.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - // show more details - Intent intent = new Intent(getActivity() - .getApplicationContext(), MoreCopyInformation.class); - intent.putExtra("recordInfo", record); - startActivity(intent); - } - }); - - if (list_size > record.copyInformationList.size()) - list_size = record.copyInformationList.size(); - - // insert into main view - LinearLayout insertPoint = (LinearLayout) layout - .findViewById(R.id.record_details_copy_information); - addCopyInfo(0, list_size, inflater, insertPoint); - - return layout; - } - - @Override - public void onSaveInstanceState(Bundle outState) { - outState.putSerializable("recordInfo", record); - outState.putInt("position", this.position); - outState.putInt("total", this.total); - super.onSaveInstanceState(outState); - } - - public void addCopyInfo(int start, int stop, LayoutInflater inflater, - LinearLayout insertPoint) { - - for (int i = start; i < stop; i++) { - - View copy_info_view = inflater.inflate(R.layout.copy_information, - null); - - // fill in any details dynamically here - TextView library = (TextView) copy_info_view - .findViewById(R.id.copy_information_library); - TextView call_number = (TextView) copy_info_view - .findViewById(R.id.copy_information_call_number); - TextView copy_location = (TextView) copy_info_view - .findViewById(R.id.copy_information_copy_location); - - library.setText(gl.getOrganizationName(record.copyInformationList - .get(i).org_id) + " "); - call_number - .setText(record.copyInformationList.get(i).call_number_sufix); - copy_location - .setText(record.copyInformationList.get(i).copy_location); - - // insert into main view - insertPoint.addView(copy_info_view, new ViewGroup.LayoutParams( - LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT)); - - LinearLayout copy_statuses = (LinearLayout) copy_info_view - .findViewById(R.id.copy_information_statuses); - - CopyInformation info = record.copyInformationList.get(i); - - Set> set = info.statusInformation.entrySet(); - - Iterator> it = set.iterator(); - - while (it.hasNext()) { - - Entry ent = it.next(); - TextView statusName = new TextView(getActivity()); - statusName.setText(ent.getKey() + " : " + ent.getValue()); - - copy_statuses.addView(statusName, new LayoutParams( - LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); - - } - - } - - } -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/utils/ui/Dashboard.java b/Open-ILS/src/Android/core/src/org/evergreen/android/utils/ui/Dashboard.java deleted file mode 100644 index 9ef43aab3a..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/utils/ui/Dashboard.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.utils.ui; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.View; -import android.view.ViewGroup; - -/** - * Custom layout that arranges children in a grid-like manner, optimizing for - * even horizontal and vertical whitespace. - */ -public class Dashboard extends ViewGroup { - - private static final int UNEVEN_GRID_PENALTY_MULTIPLIER = 10; - - private int mMaxChildWidth = 0; - private int mMaxChildHeight = 0; - - public Dashboard(Context context) { - super(context, null); - } - - public Dashboard(Context context, AttributeSet attrs) { - super(context, attrs, 0); - } - - public Dashboard(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - mMaxChildWidth = 0; - mMaxChildHeight = 0; - - // Measure once to find the maximum child size. - - int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec( - MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.AT_MOST); - int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec( - MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.AT_MOST); - - final int count = getChildCount(); - for (int i = 0; i < count; i++) { - final View child = getChildAt(i); - if (child.getVisibility() == GONE) { - continue; - } - - child.measure(childWidthMeasureSpec, childHeightMeasureSpec); - - mMaxChildWidth = Math.max(mMaxChildWidth, child.getMeasuredWidth()); - mMaxChildHeight = Math.max(mMaxChildHeight, - child.getMeasuredHeight()); - } - - // Measure again for each child to be exactly the same size. - - childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(mMaxChildWidth, - MeasureSpec.EXACTLY); - childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(mMaxChildHeight, - MeasureSpec.EXACTLY); - - for (int i = 0; i < count; i++) { - final View child = getChildAt(i); - if (child.getVisibility() == GONE) { - continue; - } - - child.measure(childWidthMeasureSpec, childHeightMeasureSpec); - } - - setMeasuredDimension(resolveSize(mMaxChildWidth, widthMeasureSpec), - resolveSize(mMaxChildHeight, heightMeasureSpec)); - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - int width = r - l; - int height = b - t; - - final int count = getChildCount(); - - // Calculate the number of visible children. - int visibleCount = 0; - for (int i = 0; i < count; i++) { - final View child = getChildAt(i); - if (child.getVisibility() == GONE) { - continue; - } - ++visibleCount; - } - - if (visibleCount == 0) { - return; - } - - // Calculate what number of rows and columns will optimize for even - // horizontal and - // vertical whitespace between items. Start with a 1 x N grid, then try - // 2 x N, and so on. - int bestSpaceDifference = Integer.MAX_VALUE; - int spaceDifference; - - // Horizontal and vertical space between items - int hSpace = 0; - int vSpace = 0; - - int cols = 1; - int rows; - - while (true) { - rows = (visibleCount - 1) / cols + 1; - - hSpace = ((width - mMaxChildWidth * cols) / (cols + 1)); - vSpace = ((height - mMaxChildHeight * rows) / (rows + 1)); - - spaceDifference = Math.abs(vSpace - hSpace); - if (rows * cols != visibleCount) { - spaceDifference *= UNEVEN_GRID_PENALTY_MULTIPLIER; - } - - if (spaceDifference < bestSpaceDifference) { - // Found a better whitespace squareness/ratio - bestSpaceDifference = spaceDifference; - - // If we found a better whitespace squareness and there's only 1 - // row, this is - // the best we can do. - if (rows == 1) { - break; - } - } else { - // This is a worse whitespace ratio, use the previous value of - // cols and exit. - --cols; - rows = (visibleCount - 1) / cols + 1; - hSpace = ((width - mMaxChildWidth * cols) / (cols + 1)); - vSpace = ((height - mMaxChildHeight * rows) / (rows + 1)); - break; - } - - ++cols; - } - - // Lay out children based on calculated best-fit number of rows and - // cols. - - // If we chose a layout that has negative horizontal or vertical space, - // force it to zero. - hSpace = Math.max(0, hSpace); - vSpace = Math.max(0, vSpace); - - // Re-use width/height variables to be child width/height. - width = (width - hSpace * (cols + 1)) / cols; - height = (height - vSpace * (rows + 1)) / rows; - - int left, top; - int col, row; - int visibleIndex = 0; - for (int i = 0; i < count; i++) { - final View child = getChildAt(i); - if (child.getVisibility() == GONE) { - continue; - } - - row = visibleIndex / cols; - col = visibleIndex % cols; - - left = hSpace * (col + 1) + width * col; - top = vSpace * (row + 1) + height * row; - - child.layout(left, top, (hSpace == 0 && col == cols - 1) ? r - : (left + width), (vSpace == 0 && row == rows - 1) ? b - : (top + height)); - ++visibleIndex; - } - } -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/utils/ui/PageIndicator.java b/Open-ILS/src/Android/core/src/org/evergreen/android/utils/ui/PageIndicator.java deleted file mode 100644 index 80d14b2e6d..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/utils/ui/PageIndicator.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ - -package org.evergreen.android.utils.ui; - -import android.support.v4.view.ViewPager; - -/** - * A PageIndicator is responsible to show an visual indicator on the total views - * number and the current visible view. - */ -public interface PageIndicator extends ViewPager.OnPageChangeListener { - /** - * Bind the indicator to a ViewPager. - * - * @param view - */ - void setViewPager(ViewPager view); - - /** - * Bind the indicator to a ViewPager. - * - * @param view - * @param initialPosition - */ - void setViewPager(ViewPager view, int initialPosition); - - /** - *

- * Set the current page of both the ViewPager and indicator. - *

- * - *

- * This must be used if you need to set the page before the - * views are drawn on screen (e.g., default start page). - *

- * - * @param item - */ - void setCurrentItem(int item); - - /** - * Set a page change listener which will receive forwarded events. - * - * @param listener - */ - void setOnPageChangeListener(ViewPager.OnPageChangeListener listener); - - /** - * Notify the indicator that the fragment list has changed. - */ - void notifyDataSetChanged(); -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/utils/ui/TabPageIndicator.java b/Open-ILS/src/Android/core/src/org/evergreen/android/utils/ui/TabPageIndicator.java deleted file mode 100644 index 2f39281bfe..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/utils/ui/TabPageIndicator.java +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ - -package org.evergreen.android.utils.ui; - -import static android.view.ViewGroup.LayoutParams; - -import org.evergreen.android.R; - -import android.content.Context; -import android.support.v4.view.PagerAdapter; -import android.support.v4.view.ViewPager; -import android.support.v4.view.ViewPager.OnPageChangeListener; -import android.util.AttributeSet; -import android.view.View; -import android.view.ViewGroup; -import android.widget.HorizontalScrollView; -import android.widget.LinearLayout; -import android.widget.TextView; - -/** - * This widget implements the dynamic action bar tab behavior that can change - * across different configurations or circumstances. - */ -public class TabPageIndicator extends HorizontalScrollView implements - PageIndicator { - /** Title text used when no title is provided by the adapter. */ - private static final CharSequence EMPTY_TITLE = ""; - - /** - * Interface for a callback when the selected tab has been reselected. - */ - public interface OnTabReselectedListener { - /** - * Callback when the selected tab has been reselected. - * - * @param position - * Position of the current center item. - */ - void onTabReselected(int position); - } - - private Runnable mTabSelector; - - private final OnClickListener mTabClickListener = new OnClickListener() { - public void onClick(View view) { - TabView tabView = (TabView) view; - final int oldSelected = mViewPager.getCurrentItem(); - final int newSelected = tabView.getIndex(); - mViewPager.setCurrentItem(newSelected); - if (oldSelected == newSelected && mTabReselectedListener != null) { - mTabReselectedListener.onTabReselected(newSelected); - } - } - }; - - private final LinearLayout mTabLayout; - private ViewPager mViewPager; - private ViewPager.OnPageChangeListener mListener; - - private int mMaxTabWidth; - private int mSelectedTabIndex; - - private OnTabReselectedListener mTabReselectedListener; - - public TabPageIndicator(Context context) { - this(context, null); - } - - public TabPageIndicator(Context context, AttributeSet attrs) { - super(context, attrs); - setHorizontalScrollBarEnabled(false); - - mTabLayout = new LinearLayout(getContext()); - addView(mTabLayout, new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT)); - } - - public void setOnTabReselectedListener(OnTabReselectedListener listener) { - mTabReselectedListener = listener; - } - - @Override - public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - final int widthMode = MeasureSpec.getMode(widthMeasureSpec); - final boolean lockedExpanded = widthMode == MeasureSpec.EXACTLY; - setFillViewport(lockedExpanded); - - final int childCount = mTabLayout.getChildCount(); - if (childCount > 1 - && (widthMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.AT_MOST)) { - if (childCount > 2) { - mMaxTabWidth = (int) (MeasureSpec.getSize(widthMeasureSpec) * 0.4f); - } else { - mMaxTabWidth = MeasureSpec.getSize(widthMeasureSpec) / 2; - } - } else { - mMaxTabWidth = -1; - } - - final int oldWidth = getMeasuredWidth(); - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - final int newWidth = getMeasuredWidth(); - - if (lockedExpanded && oldWidth != newWidth) { - // Recenter the tab display if we're at a new (scrollable) size. - setCurrentItem(mSelectedTabIndex); - } - } - - private void animateToTab(final int position) { - final View tabView = mTabLayout.getChildAt(position); - if (mTabSelector != null) { - removeCallbacks(mTabSelector); - } - mTabSelector = new Runnable() { - public void run() { - final int scrollPos = tabView.getLeft() - - (getWidth() - tabView.getWidth()) / 2; - smoothScrollTo(scrollPos, 0); - mTabSelector = null; - } - }; - post(mTabSelector); - } - - @Override - public void onAttachedToWindow() { - super.onAttachedToWindow(); - if (mTabSelector != null) { - // Re-post the selector we saved - post(mTabSelector); - } - } - - @Override - public void onDetachedFromWindow() { - super.onDetachedFromWindow(); - if (mTabSelector != null) { - removeCallbacks(mTabSelector); - } - } - - private void addTab(CharSequence text, int index) { - final TabView tabView = new TabView(getContext()); - tabView.mIndex = index; - tabView.setFocusable(true); - tabView.setOnClickListener(mTabClickListener); - tabView.setText(text); - - mTabLayout.addView(tabView, new LinearLayout.LayoutParams(0, - LayoutParams.MATCH_PARENT, 1)); - } - - @Override - public void onPageScrollStateChanged(int arg0) { - if (mListener != null) { - mListener.onPageScrollStateChanged(arg0); - } - } - - @Override - public void onPageScrolled(int arg0, float arg1, int arg2) { - if (mListener != null) { - mListener.onPageScrolled(arg0, arg1, arg2); - } - } - - @Override - public void onPageSelected(int arg0) { - setCurrentItem(arg0); - if (mListener != null) { - mListener.onPageSelected(arg0); - } - } - - @Override - public void setViewPager(ViewPager view) { - if (mViewPager == view) { - return; - } - if (mViewPager != null) { - mViewPager.setOnPageChangeListener(null); - } - final PagerAdapter adapter = view.getAdapter(); - if (adapter == null) { - throw new IllegalStateException( - "ViewPager does not have adapter instance."); - } - mViewPager = view; - view.setOnPageChangeListener(this); - notifyDataSetChanged(); - } - - public void notifyDataSetChanged() { - mTabLayout.removeAllViews(); - PagerAdapter adapter = mViewPager.getAdapter(); - final int count = adapter.getCount(); - for (int i = 0; i < count; i++) { - CharSequence title = adapter.getPageTitle(i); - if (title == null) { - title = EMPTY_TITLE; - } - addTab(title, i); - } - if (mSelectedTabIndex > count) { - mSelectedTabIndex = count - 1; - } - setCurrentItem(mSelectedTabIndex); - requestLayout(); - } - - @Override - public void setViewPager(ViewPager view, int initialPosition) { - setViewPager(view); - setCurrentItem(initialPosition); - } - - @Override - public void setCurrentItem(int item) { - if (mViewPager == null) { - throw new IllegalStateException("ViewPager has not been bound."); - } - mSelectedTabIndex = item; - mViewPager.setCurrentItem(item); - - final int tabCount = mTabLayout.getChildCount(); - for (int i = 0; i < tabCount; i++) { - final View child = mTabLayout.getChildAt(i); - final boolean isSelected = (i == item); - child.setSelected(isSelected); - if (isSelected) { - animateToTab(item); - } - } - } - - @Override - public void setOnPageChangeListener(OnPageChangeListener listener) { - mListener = listener; - } - - private class TabView extends TextView { - private int mIndex; - - public TabView(Context context) { - super(context, null, R.attr.vpiTabPageIndicatorStyle); - } - - @Override - public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - - // Re-measure if we went beyond our maximum size. - if (mMaxTabWidth > 0 && getMeasuredWidth() > mMaxTabWidth) { - super.onMeasure(MeasureSpec.makeMeasureSpec(mMaxTabWidth, - MeasureSpec.EXACTLY), heightMeasureSpec); - } - } - - public int getIndex() { - return mIndex; - } - } -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/utils/ui/TestFragment.java b/Open-ILS/src/Android/core/src/org/evergreen/android/utils/ui/TestFragment.java deleted file mode 100644 index b29c288c81..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/utils/ui/TestFragment.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.utils.ui; - -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.view.Gravity; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.LinearLayout; -import android.widget.LinearLayout.LayoutParams; -import android.widget.TextView; - -public final class TestFragment extends Fragment { - private static final String KEY_CONTENT = "TestFragment:Content"; - - public static TestFragment newInstance(String content) { - TestFragment fragment = new TestFragment(); - - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < 20; i++) { - builder.append(content).append(" "); - } - builder.deleteCharAt(builder.length() - 1); - fragment.mContent = builder.toString(); - - return fragment; - } - - private String mContent = "???"; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - if ((savedInstanceState != null) - && savedInstanceState.containsKey(KEY_CONTENT)) { - mContent = savedInstanceState.getString(KEY_CONTENT); - } - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - TextView text = new TextView(getActivity()); - text.setGravity(Gravity.CENTER); - text.setText(mContent); - text.setTextSize(20 * getResources().getDisplayMetrics().density); - text.setPadding(20, 20, 20, 20); - - LinearLayout layout = new LinearLayout(getActivity()); - layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, - LayoutParams.MATCH_PARENT)); - layout.setGravity(Gravity.CENTER); - layout.addView(text); - - return layout; - } - - @Override - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - outState.putString(KEY_CONTENT, mContent); - } -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/utils/ui/TestFragmentAdapter.java b/Open-ILS/src/Android/core/src/org/evergreen/android/utils/ui/TestFragmentAdapter.java deleted file mode 100644 index ec9077cf86..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/utils/ui/TestFragmentAdapter.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.utils.ui; - -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.support.v4.app.FragmentPagerAdapter; - -public class TestFragmentAdapter extends FragmentPagerAdapter { - protected static final String[] CONTENT = new String[] { "This", "Is", "A", - "Test", }; - - private int mCount = CONTENT.length; - - public TestFragmentAdapter(FragmentManager fm) { - super(fm); - } - - @Override - public Fragment getItem(int position) { - return TestFragment.newInstance(CONTENT[position % CONTENT.length]); - } - - @Override - public int getCount() { - return mCount; - } - -} \ No newline at end of file diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/utils/ui/TitlePageIndicator.java b/Open-ILS/src/Android/core/src/org/evergreen/android/utils/ui/TitlePageIndicator.java deleted file mode 100644 index 5b25c2bc05..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/utils/ui/TitlePageIndicator.java +++ /dev/null @@ -1,881 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.utils.ui; - -import java.util.ArrayList; - -import org.evergreen.android.R; - -import android.content.Context; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.Rect; -import android.graphics.Typeface; -import android.os.Parcel; -import android.os.Parcelable; -import android.support.v4.view.MotionEventCompat; -import android.support.v4.view.PagerAdapter; -import android.support.v4.view.ViewConfigurationCompat; -import android.support.v4.view.ViewPager; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewConfiguration; - -/** - * A TitlePageIndicator is a PageIndicator which displays the title of left view - * (if exist), the title of the current select view (centered) and the title of - * the right view (if exist). When the user scrolls the ViewPager then titles - * are also scrolled. - */ -public class TitlePageIndicator extends View implements PageIndicator { - /** - * Percentage indicating what percentage of the screen width away from - * center should the underline be fully faded. A value of 0.25 means that - * halfway between the center of the screen and an edge. - */ - private static final float SELECTION_FADE_PERCENTAGE = 0.25f; - - /** - * Percentage indicating what percentage of the screen width away from - * center should the selected text bold turn off. A value of 0.05 means that - * 10% between the center and an edge. - */ - private static final float BOLD_FADE_PERCENTAGE = 0.05f; - - /** - * Title text used when no title is provided by the adapter. - */ - private static final String EMPTY_TITLE = ""; - - /** - * Interface for a callback when the center item has been clicked. - */ - public interface OnCenterItemClickListener { - /** - * Callback when the center item has been clicked. - * - * @param position - * Position of the current center item. - */ - void onCenterItemClick(int position); - } - - public enum IndicatorStyle { - None(0), Triangle(1), Underline(2); - - public final int value; - - private IndicatorStyle(int value) { - this.value = value; - } - - public static IndicatorStyle fromValue(int value) { - for (IndicatorStyle style : IndicatorStyle.values()) { - if (style.value == value) { - return style; - } - } - return null; - } - } - - private ViewPager mViewPager; - private ViewPager.OnPageChangeListener mListener; - private PagerAdapter mPagerAdapter; - private int mCurrentPage = -1; - private float mPageOffset; - private int mScrollState; - private final Paint mPaintText = new Paint(); - private boolean mBoldText; - private int mColorText; - private int mColorSelected; - private Path mPath = new Path(); - private final Rect mBounds = new Rect(); - private final Paint mPaintFooterLine = new Paint(); - private IndicatorStyle mFooterIndicatorStyle; - private final Paint mPaintFooterIndicator = new Paint(); - private float mFooterIndicatorHeight; - private float mFooterIndicatorUnderlinePadding; - private float mFooterPadding; - private float mTitlePadding; - private float mTopPadding; - /** Left and right side padding for not active view titles. */ - private float mClipPadding; - private float mFooterLineHeight; - - private static final int INVALID_POINTER = -1; - - private int mTouchSlop; - private float mLastMotionX = -1; - private int mActivePointerId = INVALID_POINTER; - private boolean mIsDragging; - - private OnCenterItemClickListener mCenterItemClickListener; - - public TitlePageIndicator(Context context) { - this(context, null); - } - - public TitlePageIndicator(Context context, AttributeSet attrs) { - this(context, attrs, R.attr.vpiTitlePageIndicatorStyle); - } - - public TitlePageIndicator(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - if (isInEditMode()) - return; - - // Load defaults from resources - final Resources res = getResources(); - final int defaultFooterColor = res - .getColor(R.color.default_title_indicator_footer_color); - final float defaultFooterLineHeight = res - .getDimension(R.dimen.default_title_indicator_footer_line_height); - final int defaultFooterIndicatorStyle = res - .getInteger(R.integer.default_title_indicator_footer_indicator_style); - final float defaultFooterIndicatorHeight = res - .getDimension(R.dimen.default_title_indicator_footer_indicator_height); - final float defaultFooterIndicatorUnderlinePadding = res - .getDimension(R.dimen.default_title_indicator_footer_indicator_underline_padding); - final float defaultFooterPadding = res - .getDimension(R.dimen.default_title_indicator_footer_padding); - final int defaultSelectedColor = res - .getColor(R.color.default_title_indicator_selected_color); - final boolean defaultSelectedBold = res - .getBoolean(R.bool.default_title_indicator_selected_bold); - final int defaultTextColor = res - .getColor(R.color.default_title_indicator_text_color); - final float defaultTextSize = res - .getDimension(R.dimen.default_title_indicator_text_size); - final float defaultTitlePadding = res - .getDimension(R.dimen.default_title_indicator_title_padding); - final float defaultClipPadding = res - .getDimension(R.dimen.default_title_indicator_clip_padding); - final float defaultTopPadding = res - .getDimension(R.dimen.default_title_indicator_top_padding); - - // Retrieve styles attributes - TypedArray a = context.obtainStyledAttributes(attrs, - R.styleable.TitlePageIndicator, defStyle, 0); - - // Retrieve the colors to be used for this view and apply them. - mFooterLineHeight = a.getDimension( - R.styleable.TitlePageIndicator_footerLineHeight, - defaultFooterLineHeight); - mFooterIndicatorStyle = IndicatorStyle.fromValue(a.getInteger( - R.styleable.TitlePageIndicator_footerIndicatorStyle, - defaultFooterIndicatorStyle)); - mFooterIndicatorHeight = a.getDimension( - R.styleable.TitlePageIndicator_footerIndicatorHeight, - defaultFooterIndicatorHeight); - mFooterIndicatorUnderlinePadding = a.getDimension( - R.styleable.TitlePageIndicator_footerIndicatorUnderlinePadding, - defaultFooterIndicatorUnderlinePadding); - mFooterPadding = a.getDimension( - R.styleable.TitlePageIndicator_footerPadding, - defaultFooterPadding); - mTopPadding = a.getDimension(R.styleable.TitlePageIndicator_topPadding, - defaultTopPadding); - mTitlePadding = a.getDimension( - R.styleable.TitlePageIndicator_titlePadding, - defaultTitlePadding); - mClipPadding = a.getDimension( - R.styleable.TitlePageIndicator_clipPadding, defaultClipPadding); - mColorSelected = a.getColor( - R.styleable.TitlePageIndicator_selectedColor, - defaultSelectedColor); - mColorText = a.getColor( - R.styleable.TitlePageIndicator_android_textColor, - defaultTextColor); - mBoldText = a.getBoolean(R.styleable.TitlePageIndicator_selectedBold, - defaultSelectedBold); - - final float textSize = a.getDimension( - R.styleable.TitlePageIndicator_android_textSize, - defaultTextSize); - final int footerColor = a.getColor( - R.styleable.TitlePageIndicator_footerColor, defaultFooterColor); - mPaintText.setTextSize(textSize); - mPaintText.setAntiAlias(true); - mPaintFooterLine.setStyle(Paint.Style.FILL_AND_STROKE); - mPaintFooterLine.setStrokeWidth(mFooterLineHeight); - mPaintFooterLine.setColor(footerColor); - mPaintFooterIndicator.setStyle(Paint.Style.FILL_AND_STROKE); - mPaintFooterIndicator.setColor(footerColor); - - a.recycle(); - - final ViewConfiguration configuration = ViewConfiguration.get(context); - mTouchSlop = ViewConfigurationCompat - .getScaledPagingTouchSlop(configuration); - } - - public int getFooterColor() { - return mPaintFooterLine.getColor(); - } - - public void setFooterColor(int footerColor) { - mPaintFooterLine.setColor(footerColor); - mPaintFooterIndicator.setColor(footerColor); - invalidate(); - } - - public float getFooterLineHeight() { - return mFooterLineHeight; - } - - public void setFooterLineHeight(float footerLineHeight) { - mFooterLineHeight = footerLineHeight; - mPaintFooterLine.setStrokeWidth(mFooterLineHeight); - invalidate(); - } - - public float getFooterIndicatorHeight() { - return mFooterIndicatorHeight; - } - - public void setFooterIndicatorHeight(float footerTriangleHeight) { - mFooterIndicatorHeight = footerTriangleHeight; - invalidate(); - } - - public float getFooterIndicatorPadding() { - return mFooterPadding; - } - - public void setFooterIndicatorPadding(float footerIndicatorPadding) { - mFooterPadding = footerIndicatorPadding; - invalidate(); - } - - public IndicatorStyle getFooterIndicatorStyle() { - return mFooterIndicatorStyle; - } - - public void setFooterIndicatorStyle(IndicatorStyle indicatorStyle) { - mFooterIndicatorStyle = indicatorStyle; - invalidate(); - } - - public int getSelectedColor() { - return mColorSelected; - } - - public void setSelectedColor(int selectedColor) { - mColorSelected = selectedColor; - invalidate(); - } - - public boolean isSelectedBold() { - return mBoldText; - } - - public void setSelectedBold(boolean selectedBold) { - mBoldText = selectedBold; - invalidate(); - } - - public int getTextColor() { - return mColorText; - } - - public void setTextColor(int textColor) { - mPaintText.setColor(textColor); - mColorText = textColor; - invalidate(); - } - - public float getTextSize() { - return mPaintText.getTextSize(); - } - - public void setTextSize(float textSize) { - mPaintText.setTextSize(textSize); - invalidate(); - } - - public float getTitlePadding() { - return this.mTitlePadding; - } - - public void setTitlePadding(float titlePadding) { - mTitlePadding = titlePadding; - invalidate(); - } - - public float getTopPadding() { - return this.mTopPadding; - } - - public void setTopPadding(float topPadding) { - mTopPadding = topPadding; - invalidate(); - } - - public float getClipPadding() { - return this.mClipPadding; - } - - public void setClipPadding(float clipPadding) { - mClipPadding = clipPadding; - invalidate(); - } - - public void setTypeface(Typeface typeface) { - mPaintText.setTypeface(typeface); - invalidate(); - } - - public Typeface getTypeface() { - return mPaintText.getTypeface(); - } - - /* - * (non-Javadoc) - * - * @see android.view.View#onDraw(android.graphics.Canvas) - */ - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - - if (mViewPager == null) { - return; - } - final int count = mViewPager.getAdapter().getCount(); - if (count == 0) { - return; - } - - // mCurrentPage is -1 on first start and after orientation changed. If - // so, retrieve the correct index from viewpager. - if (mCurrentPage == -1 && mViewPager != null) - mCurrentPage = mViewPager.getCurrentItem(); - - // Calculate views bounds - ArrayList bounds = calculateAllBounds(mPaintText); - final int boundsSize = bounds.size(); - - // Make sure we're on a page that still exists - if (mCurrentPage >= boundsSize) { - setCurrentItem(boundsSize - 1); - return; - } - - final int countMinusOne = count - 1; - final float halfWidth = getWidth() / 2f; - final int left = getLeft(); - final float leftClip = left + mClipPadding; - final int width = getWidth(); - final int height = getHeight(); - final int right = left + width; - final float rightClip = right - mClipPadding; - - int page = mCurrentPage; - float offsetPercent; - if (mPageOffset <= 0.5) { - offsetPercent = mPageOffset; - } else { - page += 1; - offsetPercent = 1 - mPageOffset; - } - final boolean currentSelected = (offsetPercent <= SELECTION_FADE_PERCENTAGE); - final boolean currentBold = (offsetPercent <= BOLD_FADE_PERCENTAGE); - final float selectedPercent = (SELECTION_FADE_PERCENTAGE - offsetPercent) - / SELECTION_FADE_PERCENTAGE; - - // Verify if the current view must be clipped to the screen - Rect curPageBound = bounds.get(mCurrentPage); - float curPageWidth = curPageBound.right - curPageBound.left; - if (curPageBound.left < leftClip) { - // Try to clip to the screen (left side) - clipViewOnTheLeft(curPageBound, curPageWidth, left); - } - if (curPageBound.right > rightClip) { - // Try to clip to the screen (right side) - clipViewOnTheRight(curPageBound, curPageWidth, right); - } - - // Left views starting from the current position - if (mCurrentPage > 0) { - for (int i = mCurrentPage - 1; i >= 0; i--) { - Rect bound = bounds.get(i); - // Is left side is outside the screen - if (bound.left < leftClip) { - int w = bound.right - bound.left; - // Try to clip to the screen (left side) - clipViewOnTheLeft(bound, w, left); - // Except if there's an intersection with the right view - Rect rightBound = bounds.get(i + 1); - // Intersection - if (bound.right + mTitlePadding > rightBound.left) { - bound.left = (int) (rightBound.left - w - mTitlePadding); - bound.right = bound.left + w; - } - } - } - } - // Right views starting from the current position - if (mCurrentPage < countMinusOne) { - for (int i = mCurrentPage + 1; i < count; i++) { - Rect bound = bounds.get(i); - // If right side is outside the screen - if (bound.right > rightClip) { - int w = bound.right - bound.left; - // Try to clip to the screen (right side) - clipViewOnTheRight(bound, w, right); - // Except if there's an intersection with the left view - Rect leftBound = bounds.get(i - 1); - // Intersection - if (bound.left - mTitlePadding < leftBound.right) { - bound.left = (int) (leftBound.right + mTitlePadding); - bound.right = bound.left + w; - } - } - } - } - - // Now draw views - int colorTextAlpha = mColorText >>> 24; - for (int i = 0; i < count; i++) { - // Get the title - Rect bound = bounds.get(i); - // Only if one side is visible - if ((bound.left > left && bound.left < right) - || (bound.right > left && bound.right < right)) { - final boolean currentPage = (i == page); - final CharSequence pageTitle = getTitle(i); - - // Only set bold if we are within bounds - mPaintText.setFakeBoldText(currentPage && currentBold - && mBoldText); - - // Draw text as unselected - mPaintText.setColor(mColorText); - if (currentPage && currentSelected) { - // Fade out/in unselected text as the selected text fades - // in/out - mPaintText.setAlpha(colorTextAlpha - - (int) (colorTextAlpha * selectedPercent)); - } - canvas.drawText(pageTitle, 0, pageTitle.length(), bound.left, - bound.bottom + mTopPadding, mPaintText); - - // If we are within the selected bounds draw the selected text - if (currentPage && currentSelected) { - mPaintText.setColor(mColorSelected); - mPaintText - .setAlpha((int) ((mColorSelected >>> 24) * selectedPercent)); - canvas.drawText(pageTitle, 0, pageTitle.length(), - bound.left, bound.bottom + mTopPadding, mPaintText); - } - } - } - - // Draw the footer line - mPath.reset(); - mPath.moveTo(0, height - mFooterLineHeight / 2f); - mPath.lineTo(width, height - mFooterLineHeight / 2f); - mPath.close(); - canvas.drawPath(mPath, mPaintFooterLine); - - switch (mFooterIndicatorStyle) { - case Triangle: - mPath.reset(); - mPath.moveTo(halfWidth, height - mFooterLineHeight - - mFooterIndicatorHeight); - mPath.lineTo(halfWidth + mFooterIndicatorHeight, height - - mFooterLineHeight); - mPath.lineTo(halfWidth - mFooterIndicatorHeight, height - - mFooterLineHeight); - mPath.close(); - canvas.drawPath(mPath, mPaintFooterIndicator); - break; - - case Underline: - if (!currentSelected || page >= boundsSize) { - break; - } - - Rect underlineBounds = bounds.get(page); - mPath.reset(); - mPath.moveTo(underlineBounds.left - - mFooterIndicatorUnderlinePadding, height - - mFooterLineHeight); - mPath.lineTo(underlineBounds.right - + mFooterIndicatorUnderlinePadding, height - - mFooterLineHeight); - mPath.lineTo(underlineBounds.right - + mFooterIndicatorUnderlinePadding, height - - mFooterLineHeight - mFooterIndicatorHeight); - mPath.lineTo(underlineBounds.left - - mFooterIndicatorUnderlinePadding, height - - mFooterLineHeight - mFooterIndicatorHeight); - mPath.close(); - - mPaintFooterIndicator.setAlpha((int) (0xFF * selectedPercent)); - canvas.drawPath(mPath, mPaintFooterIndicator); - mPaintFooterIndicator.setAlpha(0xFF); - break; - } - } - - public boolean onTouchEvent(android.view.MotionEvent ev) { - if (super.onTouchEvent(ev)) { - return true; - } - if ((mViewPager == null) || (mViewPager.getAdapter().getCount() == 0)) { - return false; - } - - final int action = ev.getAction(); - - switch (action & MotionEventCompat.ACTION_MASK) { - case MotionEvent.ACTION_DOWN: - mActivePointerId = MotionEventCompat.getPointerId(ev, 0); - mLastMotionX = ev.getX(); - break; - - case MotionEvent.ACTION_MOVE: { - final int activePointerIndex = MotionEventCompat.findPointerIndex( - ev, mActivePointerId); - final float x = MotionEventCompat.getX(ev, activePointerIndex); - final float deltaX = x - mLastMotionX; - - if (!mIsDragging) { - if (Math.abs(deltaX) > mTouchSlop) { - mIsDragging = true; - } - } - - if (mIsDragging) { - mLastMotionX = x; - if (mViewPager.isFakeDragging() || mViewPager.beginFakeDrag()) { - mViewPager.fakeDragBy(deltaX); - } - } - - break; - } - - case MotionEvent.ACTION_CANCEL: - case MotionEvent.ACTION_UP: - if (!mIsDragging) { - final int count = mViewPager.getAdapter().getCount(); - final int width = getWidth(); - final float halfWidth = width / 2f; - final float sixthWidth = width / 6f; - final float leftThird = halfWidth - sixthWidth; - final float rightThird = halfWidth + sixthWidth; - final float eventX = ev.getX(); - - if (eventX < leftThird) { - if (mCurrentPage > 0) { - mViewPager.setCurrentItem(mCurrentPage - 1); - return true; - } - } else if (eventX > rightThird) { - if (mCurrentPage < count - 1) { - mViewPager.setCurrentItem(mCurrentPage + 1); - return true; - } - } else { - // Middle third - if (mCenterItemClickListener != null) { - mCenterItemClickListener - .onCenterItemClick(mCurrentPage); - } - } - } - - mIsDragging = false; - mActivePointerId = INVALID_POINTER; - if (mViewPager.isFakeDragging()) - mViewPager.endFakeDrag(); - break; - - case MotionEventCompat.ACTION_POINTER_DOWN: { - final int index = MotionEventCompat.getActionIndex(ev); - final float x = MotionEventCompat.getX(ev, index); - mLastMotionX = x; - mActivePointerId = MotionEventCompat.getPointerId(ev, index); - break; - } - - case MotionEventCompat.ACTION_POINTER_UP: - final int pointerIndex = MotionEventCompat.getActionIndex(ev); - final int pointerId = MotionEventCompat.getPointerId(ev, - pointerIndex); - if (pointerId == mActivePointerId) { - final int newPointerIndex = pointerIndex == 0 ? 1 : 0; - mActivePointerId = MotionEventCompat.getPointerId(ev, - newPointerIndex); - } - mLastMotionX = MotionEventCompat.getX(ev, - MotionEventCompat.findPointerIndex(ev, mActivePointerId)); - break; - } - - return true; - }; - - /** - * Set bounds for the right textView including clip padding. - * - * @param curViewBound - * current bounds. - * @param curViewWidth - * width of the view. - */ - private void clipViewOnTheRight(Rect curViewBound, float curViewWidth, - int right) { - curViewBound.right = (int) (right - mClipPadding); - curViewBound.left = (int) (curViewBound.right - curViewWidth); - } - - /** - * Set bounds for the left textView including clip padding. - * - * @param curViewBound - * current bounds. - * @param curViewWidth - * width of the view. - */ - private void clipViewOnTheLeft(Rect curViewBound, float curViewWidth, - int left) { - curViewBound.left = (int) (left + mClipPadding); - curViewBound.right = (int) (mClipPadding + curViewWidth); - } - - /** - * Calculate views bounds and scroll them according to the current index - * - * @param paint - * @return - */ - private ArrayList calculateAllBounds(Paint paint) { - ArrayList list = new ArrayList(); - // For each views (If no values then add a fake one) - final int count = mViewPager.getAdapter().getCount(); - final int width = getWidth(); - final int halfWidth = width / 2; - for (int i = 0; i < count; i++) { - Rect bounds = calcBounds(i, paint); - int w = bounds.right - bounds.left; - int h = bounds.bottom - bounds.top; - bounds.left = (int) (halfWidth - (w / 2f) + ((i - mCurrentPage - mPageOffset) * width)); - bounds.right = bounds.left + w; - bounds.top = 0; - bounds.bottom = h; - list.add(bounds); - } - - return list; - } - - /** - * Calculate the bounds for a view's title - * - * @param index - * @param paint - * @return - */ - private Rect calcBounds(int index, Paint paint) { - // Calculate the text bounds - Rect bounds = new Rect(); - CharSequence title = getTitle(index); - bounds.right = (int) paint.measureText(title, 0, title.length()); - bounds.bottom = (int) (paint.descent() - paint.ascent()); - return bounds; - } - - @Override - public void setViewPager(ViewPager view) { - if (mViewPager == view) { - return; - } - if (mViewPager != null) { - mViewPager.setOnPageChangeListener(null); - } - mPagerAdapter = view.getAdapter(); - if (mPagerAdapter == null) { - throw new IllegalStateException( - "ViewPager does not have adapter instance."); - } - mViewPager = view; - mViewPager.setOnPageChangeListener(this); - invalidate(); - } - - @Override - public void setViewPager(ViewPager view, int initialPosition) { - setViewPager(view); - setCurrentItem(initialPosition); - } - - @Override - public void notifyDataSetChanged() { - invalidate(); - } - - /** - * Set a callback listener for the center item click. - * - * @param listener - * Callback instance. - */ - public void setOnCenterItemClickListener(OnCenterItemClickListener listener) { - mCenterItemClickListener = listener; - } - - @Override - public void setCurrentItem(int item) { - if (mViewPager == null) { - throw new IllegalStateException("ViewPager has not been bound."); - } - mViewPager.setCurrentItem(item); - mCurrentPage = item; - invalidate(); - } - - @Override - public void onPageScrollStateChanged(int state) { - mScrollState = state; - - if (mListener != null) { - mListener.onPageScrollStateChanged(state); - } - } - - @Override - public void onPageScrolled(int position, float positionOffset, - int positionOffsetPixels) { - mCurrentPage = position; - mPageOffset = positionOffset; - invalidate(); - - if (mListener != null) { - mListener.onPageScrolled(position, positionOffset, - positionOffsetPixels); - } - } - - @Override - public void onPageSelected(int position) { - if (mScrollState == ViewPager.SCROLL_STATE_IDLE) { - mCurrentPage = position; - invalidate(); - } - - if (mListener != null) { - mListener.onPageSelected(position); - } - } - - @Override - public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) { - mListener = listener; - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - // Measure our width in whatever mode specified - final int measuredWidth = MeasureSpec.getSize(widthMeasureSpec); - - // Determine our height - float height = 0; - final int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec); - if (heightSpecMode == MeasureSpec.EXACTLY) { - // We were told how big to be - height = MeasureSpec.getSize(heightMeasureSpec); - } else { - // Calculate the text bounds - mBounds.setEmpty(); - mBounds.bottom = (int) (mPaintText.descent() - mPaintText.ascent()); - height = mBounds.bottom - mBounds.top + mFooterLineHeight - + mFooterPadding + mTopPadding; - if (mFooterIndicatorStyle != IndicatorStyle.None) { - height += mFooterIndicatorHeight; - } - } - final int measuredHeight = (int) height; - - setMeasuredDimension(measuredWidth, measuredHeight); - } - - @Override - public void onRestoreInstanceState(Parcelable state) { - SavedState savedState = (SavedState) state; - super.onRestoreInstanceState(savedState.getSuperState()); - mCurrentPage = savedState.currentPage; - requestLayout(); - } - - @Override - public Parcelable onSaveInstanceState() { - Parcelable superState = super.onSaveInstanceState(); - SavedState savedState = new SavedState(superState); - savedState.currentPage = mCurrentPage; - return savedState; - } - - static class SavedState extends BaseSavedState { - int currentPage; - - public SavedState(Parcelable superState) { - super(superState); - } - - private SavedState(Parcel in) { - super(in); - currentPage = in.readInt(); - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - super.writeToParcel(dest, flags); - dest.writeInt(currentPage); - } - - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - @Override - public SavedState createFromParcel(Parcel in) { - return new SavedState(in); - } - - @Override - public SavedState[] newArray(int size) { - return new SavedState[size]; - } - }; - } - - private CharSequence getTitle(int i) { - CharSequence title = mPagerAdapter.getPageTitle(i); - if (title == null) { - title = EMPTY_TITLE; - } - return title.toString(); - } -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/utils/ui/UnderlinePageIndicator.java b/Open-ILS/src/Android/core/src/org/evergreen/android/utils/ui/UnderlinePageIndicator.java deleted file mode 100644 index ec6fe2b7ec..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/utils/ui/UnderlinePageIndicator.java +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.utils.ui; - -import org.evergreen.android.R; - -import android.content.Context; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.os.Parcel; -import android.os.Parcelable; -import android.support.v4.view.MotionEventCompat; -import android.support.v4.view.ViewConfigurationCompat; -import android.support.v4.view.ViewPager; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewConfiguration; - -/** - * Draws a line for each page. The current page line is colored differently than - * the unselected page lines. - */ -public class UnderlinePageIndicator extends View implements PageIndicator { - private static final int INVALID_POINTER = -1; - private static final int FADE_FRAME_MS = 30; - - private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - - private boolean mFades; - private int mFadeDelay; - private int mFadeLength; - private int mFadeBy; - - private ViewPager mViewPager; - private ViewPager.OnPageChangeListener mListener; - private int mScrollState; - private int mCurrentPage; - private float mPositionOffset; - - private int mTouchSlop; - private float mLastMotionX = -1; - private int mActivePointerId = INVALID_POINTER; - private boolean mIsDragging; - - private final Runnable mFadeRunnable = new Runnable() { - @Override - public void run() { - final int alpha = Math.max(mPaint.getAlpha() - mFadeBy, 0); - mPaint.setAlpha(alpha); - invalidate(); - if (alpha > 0) { - postDelayed(this, FADE_FRAME_MS); - } - } - }; - - public UnderlinePageIndicator(Context context) { - this(context, null); - } - - public UnderlinePageIndicator(Context context, AttributeSet attrs) { - this(context, attrs, R.attr.vpiUnderlinePageIndicatorStyle); - } - - public UnderlinePageIndicator(Context context, AttributeSet attrs, - int defStyle) { - super(context, attrs, defStyle); - if (isInEditMode()) - return; - - final Resources res = getResources(); - - // Load defaults from resources - final boolean defaultFades = res - .getBoolean(R.bool.default_underline_indicator_fades); - final int defaultFadeDelay = res - .getInteger(R.integer.default_underline_indicator_fade_delay); - final int defaultFadeLength = res - .getInteger(R.integer.default_underline_indicator_fade_length); - final int defaultSelectedColor = res - .getColor(R.color.default_underline_indicator_selected_color); - - // Retrieve styles attributes - TypedArray a = context.obtainStyledAttributes(attrs, - R.styleable.UnderlinePageIndicator, defStyle, 0); - - setFades(a.getBoolean(R.styleable.UnderlinePageIndicator_fades, - defaultFades)); - setSelectedColor(a.getColor( - R.styleable.UnderlinePageIndicator_selectedColor, - defaultSelectedColor)); - setFadeDelay(a.getInteger(R.styleable.UnderlinePageIndicator_fadeDelay, - defaultFadeDelay)); - setFadeLength(a.getInteger( - R.styleable.UnderlinePageIndicator_fadeLength, - defaultFadeLength)); - - a.recycle(); - - final ViewConfiguration configuration = ViewConfiguration.get(context); - mTouchSlop = ViewConfigurationCompat - .getScaledPagingTouchSlop(configuration); - } - - public boolean getFades() { - return mFades; - } - - public void setFades(boolean fades) { - if (fades != mFades) { - mFades = fades; - if (fades) { - post(mFadeRunnable); - } else { - removeCallbacks(mFadeRunnable); - mPaint.setAlpha(0xFF); - invalidate(); - } - } - } - - public int getFadeDelay() { - return mFadeDelay; - } - - public void setFadeDelay(int fadeDelay) { - mFadeDelay = fadeDelay; - } - - public int getFadeLength() { - return mFadeLength; - } - - public void setFadeLength(int fadeLength) { - mFadeLength = fadeLength; - mFadeBy = 0xFF / (mFadeLength / FADE_FRAME_MS); - } - - public int getSelectedColor() { - return mPaint.getColor(); - } - - public void setSelectedColor(int selectedColor) { - mPaint.setColor(selectedColor); - invalidate(); - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - - if (mViewPager == null) { - return; - } - final int count = mViewPager.getAdapter().getCount(); - if (count == 0) { - return; - } - - if (mCurrentPage >= count) { - setCurrentItem(count - 1); - return; - } - - final int paddingLeft = getPaddingLeft(); - final float pageWidth = (getWidth() - paddingLeft - getPaddingRight()) - / (1f * count); - final float left = paddingLeft + pageWidth - * (mCurrentPage + mPositionOffset); - final float right = left + pageWidth; - final float top = getPaddingTop(); - final float bottom = getHeight() - getPaddingBottom(); - canvas.drawRect(left, top, right, bottom, mPaint); - } - - public boolean onTouchEvent(MotionEvent ev) { - if (super.onTouchEvent(ev)) { - return true; - } - if ((mViewPager == null) || (mViewPager.getAdapter().getCount() == 0)) { - return false; - } - - final int action = ev.getAction(); - - switch (action & MotionEventCompat.ACTION_MASK) { - case MotionEvent.ACTION_DOWN: - mActivePointerId = MotionEventCompat.getPointerId(ev, 0); - mLastMotionX = ev.getX(); - break; - - case MotionEvent.ACTION_MOVE: { - final int activePointerIndex = MotionEventCompat.findPointerIndex( - ev, mActivePointerId); - final float x = MotionEventCompat.getX(ev, activePointerIndex); - final float deltaX = x - mLastMotionX; - - if (!mIsDragging) { - if (Math.abs(deltaX) > mTouchSlop) { - mIsDragging = true; - } - } - - if (mIsDragging) { - mLastMotionX = x; - if (mViewPager.isFakeDragging() || mViewPager.beginFakeDrag()) { - mViewPager.fakeDragBy(deltaX); - } - } - - break; - } - - case MotionEvent.ACTION_CANCEL: - case MotionEvent.ACTION_UP: - if (!mIsDragging) { - final int count = mViewPager.getAdapter().getCount(); - final int width = getWidth(); - final float halfWidth = width / 2f; - final float sixthWidth = width / 6f; - - if ((mCurrentPage > 0) && (ev.getX() < halfWidth - sixthWidth)) { - mViewPager.setCurrentItem(mCurrentPage - 1); - return true; - } else if ((mCurrentPage < count - 1) - && (ev.getX() > halfWidth + sixthWidth)) { - mViewPager.setCurrentItem(mCurrentPage + 1); - return true; - } - } - - mIsDragging = false; - mActivePointerId = INVALID_POINTER; - if (mViewPager.isFakeDragging()) - mViewPager.endFakeDrag(); - break; - - case MotionEventCompat.ACTION_POINTER_DOWN: { - final int index = MotionEventCompat.getActionIndex(ev); - final float x = MotionEventCompat.getX(ev, index); - mLastMotionX = x; - mActivePointerId = MotionEventCompat.getPointerId(ev, index); - break; - } - - case MotionEventCompat.ACTION_POINTER_UP: - final int pointerIndex = MotionEventCompat.getActionIndex(ev); - final int pointerId = MotionEventCompat.getPointerId(ev, - pointerIndex); - if (pointerId == mActivePointerId) { - final int newPointerIndex = pointerIndex == 0 ? 1 : 0; - mActivePointerId = MotionEventCompat.getPointerId(ev, - newPointerIndex); - } - mLastMotionX = MotionEventCompat.getX(ev, - MotionEventCompat.findPointerIndex(ev, mActivePointerId)); - break; - } - - return true; - }; - - @Override - public void setViewPager(ViewPager viewPager) { - if (mViewPager == viewPager) { - return; - } - if (mViewPager != null) { - // Clear us from the old pager. - mViewPager.setOnPageChangeListener(null); - } - if (viewPager.getAdapter() == null) { - throw new IllegalStateException( - "ViewPager does not have adapter instance."); - } - mViewPager = viewPager; - mViewPager.setOnPageChangeListener(this); - invalidate(); - post(new Runnable() { - @Override - public void run() { - if (mFades) { - post(mFadeRunnable); - } - } - }); - } - - @Override - public void setViewPager(ViewPager view, int initialPosition) { - setViewPager(view); - setCurrentItem(initialPosition); - } - - @Override - public void setCurrentItem(int item) { - if (mViewPager == null) { - throw new IllegalStateException("ViewPager has not been bound."); - } - mViewPager.setCurrentItem(item); - mCurrentPage = item; - invalidate(); - } - - @Override - public void notifyDataSetChanged() { - invalidate(); - } - - @Override - public void onPageScrollStateChanged(int state) { - mScrollState = state; - - if (mListener != null) { - mListener.onPageScrollStateChanged(state); - } - } - - @Override - public void onPageScrolled(int position, float positionOffset, - int positionOffsetPixels) { - mCurrentPage = position; - mPositionOffset = positionOffset; - if (mFades) { - if (positionOffsetPixels > 0) { - removeCallbacks(mFadeRunnable); - mPaint.setAlpha(0xFF); - } else if (mScrollState != ViewPager.SCROLL_STATE_DRAGGING) { - postDelayed(mFadeRunnable, mFadeDelay); - } - } - invalidate(); - - if (mListener != null) { - mListener.onPageScrolled(position, positionOffset, - positionOffsetPixels); - } - } - - @Override - public void onPageSelected(int position) { - if (mScrollState == ViewPager.SCROLL_STATE_IDLE) { - mCurrentPage = position; - mPositionOffset = 0; - invalidate(); - mFadeRunnable.run(); - } - if (mListener != null) { - mListener.onPageSelected(position); - } - } - - @Override - public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) { - mListener = listener; - } - - @Override - public void onRestoreInstanceState(Parcelable state) { - SavedState savedState = (SavedState) state; - super.onRestoreInstanceState(savedState.getSuperState()); - mCurrentPage = savedState.currentPage; - requestLayout(); - } - - @Override - public Parcelable onSaveInstanceState() { - Parcelable superState = super.onSaveInstanceState(); - SavedState savedState = new SavedState(superState); - savedState.currentPage = mCurrentPage; - return savedState; - } - - static class SavedState extends BaseSavedState { - int currentPage; - - public SavedState(Parcelable superState) { - super(superState); - } - - private SavedState(Parcel in) { - super(in); - currentPage = in.readInt(); - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - super.writeToParcel(dest, flags); - dest.writeInt(currentPage); - } - - public static final Creator CREATOR = new Creator() { - @Override - public SavedState createFromParcel(Parcel in) { - return new SavedState(in); - } - - @Override - public SavedState[] newArray(int size) { - return new SavedState[size]; - } - }; - } -} \ No newline at end of file diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/views/AccountScreenDashboard.java b/Open-ILS/src/Android/core/src/org/evergreen/android/views/AccountScreenDashboard.java deleted file mode 100644 index 9adc1e16fc..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/views/AccountScreenDashboard.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.views; - -import org.evergreen.android.R; -import org.evergreen.android.accountAccess.bookbags.BookbagsListView; -import org.evergreen.android.accountAccess.checkout.ItemsCheckOutListView; -import org.evergreen.android.accountAccess.fines.FinesActivity; -import org.evergreen.android.accountAccess.holds.HoldsListView; -import org.evergreen.android.searchCatalog.SearchCatalogListView; -import org.evergreen.android.views.splashscreen.SplashActivity; - -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; - -public class AccountScreenDashboard extends Activity { - - /** - * onCreate - called when the activity is first created. - * - * Called when the activity is first created. This is where you should do - * all of your normal static set up: create views, bind data to lists, etc. - * This method also provides you with a Bundle containing the activity's - * previously frozen state, if there was one. - * - * Always followed by onStart(). - * - */ - - private Button homeButton = null; - - private Button myAccountButton = null; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (!SplashActivity.isAppInitialized()) { - SplashActivity.restartApp(this); - return; - } - - setContentView(R.layout.dashbord_account); - -// myAccountButton = (Button) findViewById(R.id.my_account_button); -// myAccountButton.setEnabled(false); -// myAccountButton.setOnClickListener(new OnClickListener() { -// @Override -// public void onClick(View v) { -// } -// }); - - homeButton = (Button) findViewById(R.id.action_bar_home_button); - homeButton.setText(R.string.my_account_button_text); - homeButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - - Intent intent = new Intent(getApplicationContext(), - SearchCatalogListView.class); - startActivity(intent); - } - }); - } - - /** - * onDestroy The final call you receive before your activity is destroyed. - * This can happen either because the activity is finishing (someone called - * finish() on it, or because the system is temporarily destroying this - * instance of the activity to save space. You can distinguish between these - * two scenarios with the isFinishing() method. - * - */ - - protected void onDestroy() { - super.onDestroy(); - } - - /** - * onPause Called when the system is about to start resuming a previous - * activity. This is typically used to commit unsaved changes to persistent - * data, stop animations and other things that may be consuming CPU, etc. - * Implementations of this method must be very quick because the next - * activity will not be resumed until this method returns. Followed by - * either onResume() if the activity returns back to the front, or onStop() - * if it becomes invisible to the user. - * - */ - - protected void onPause() { - super.onPause(); - } - - /** - * onRestart Called after your activity has been stopped, prior to it being - * started again. Always followed by onStart(). - * - */ - - protected void onRestart() { - super.onRestart(); - } - - /** - * onResume Called when the activity will start interacting with the user. - * At this point your activity is at the top of the activity stack, with - * user input going to it. Always followed by onPause(). - * - */ - - protected void onResume() { - super.onResume(); - } - - /** - * onStart Called when the activity is becoming visible to the user. - * Followed by onResume() if the activity comes to the foreground, or - * onStop() if it becomes hidden. - * - */ - - protected void onStart() { - super.onStart(); - } - - /** - * onStop Called when the activity is no longer visible to the user because - * another activity has been resumed and is covering this one. This may - * happen either because a new activity is being started, an existing one is - * being brought in front of this one, or this one is being destroyed. - * - * Followed by either onRestart() if this activity is coming back to - * interact with the user, or onDestroy() if this activity is going away. - */ - - protected void onStop() { - super.onStop(); - } - - public void onClickFeature(View v) { - int id = v.getId(); - if (id == R.id.account_btn_check_out) { - startActivity(new Intent(getApplicationContext(), - ItemsCheckOutListView.class)); - - } else if (id == R.id.account_btn_holds) { - startActivity(new Intent(getApplicationContext(), - HoldsListView.class)); - - } else if (id == R.id.account_btn_fines) { - startActivity(new Intent(getApplicationContext(), - FinesActivity.class)); - - } else if (id == R.id.account_btn_book_bags) { - startActivity(new Intent(getApplicationContext(), - BookbagsListView.class)); - - } - - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/views/ApplicationPreferences.java b/Open-ILS/src/Android/core/src/org/evergreen/android/views/ApplicationPreferences.java deleted file mode 100644 index 33113ea209..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/views/ApplicationPreferences.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.views; - -import java.util.Calendar; - -import org.evergreen.android.R; -import org.evergreen.android.globals.GlobalConfigs; -import org.evergreen.android.services.NotificationAlert; -import org.evergreen.android.services.PeriodicServiceBroadcastReceiver; -import org.evergreen.android.services.ScheduledIntentService; -import org.evergreen_ils.auth.Const; - -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.app.ProgressDialog; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.SharedPreferences.OnSharedPreferenceChangeListener; -import android.net.ConnectivityManager; -import android.os.Bundle; -import android.preference.PreferenceActivity; -import android.preference.PreferenceManager; -import android.provider.Settings; -import android.widget.Toast; - -public class ApplicationPreferences extends PreferenceActivity implements - OnSharedPreferenceChangeListener { - - private final String TAG = ApplicationPreferences.class.getName(); - - private ProgressDialog progressDialog; - - private ApplicationPreferences reference; - - private Context context; - - private Thread coreFilesDownload = null; - - @Override - protected void onCreate(Bundle savedInstanceState) { - - super.onCreate(savedInstanceState); - - addPreferencesFromResource(R.xml.preferences); - - context = this; - reference = this; - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - prefs.registerOnSharedPreferenceChangeListener(this); - } - - @Override - protected void onResume() { - super.onResume(); - reference = this; - } - - @Override - protected void onPause() { - super.onPause(); - reference = null; - } - - @Override - protected void onStop() { - super.onStop(); - reference = null; - } - - @Override - protected void onDestroy() { - super.onDestroy(); - reference = null; - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, - String key) { - - boolean httpAddressChange = false; - - boolean checkConnection = false; - - if (key.equals("notifications_enabled")) { - - if (sharedPreferences.getBoolean("notifications_enabled", false)) { - - Toast.makeText(context, "Set up notification updates", - Toast.LENGTH_SHORT).show(); - // if enabled register the update service to run once per day - // get a Calendar object with current time - Calendar cal = Calendar.getInstance(); - - Intent bRecvIntent = new Intent(this, - PeriodicServiceBroadcastReceiver.class); - bRecvIntent.setAction(ScheduledIntentService.ACTION); - // update the current intent if it exists - PendingIntent sender = PendingIntent.getBroadcast(this, - NotificationAlert.NOTIFICATION_INTENT - + PeriodicServiceBroadcastReceiver.INTENT_ID, - bRecvIntent, PendingIntent.FLAG_UPDATE_CURRENT); - - // Get the AlarmManager service - AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE); - am.setRepeating(AlarmManager.RTC, cal.getTimeInMillis(), - 10000 * ScheduledIntentService.SCHEDULE_TIME_INTERVAL, - sender); - } else { - Toast.makeText(context, "Disable notification updates", - Toast.LENGTH_SHORT).show(); - // cancel the service - - Intent bRecvIntent = new Intent(this, - PeriodicServiceBroadcastReceiver.class); - - // update the current intent if it exists - PendingIntent sender = PendingIntent.getBroadcast(this, - NotificationAlert.NOTIFICATION_INTENT - + PeriodicServiceBroadcastReceiver.INTENT_ID, - bRecvIntent, PendingIntent.FLAG_UPDATE_CURRENT); - - // Get the AlarmManager service - AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE); - // cancel the service - am.cancel(sender); - } - } - } - -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/views/splashscreen/LoadingTask.java b/Open-ILS/src/Android/core/src/org/evergreen/android/views/splashscreen/LoadingTask.java deleted file mode 100644 index 96a6cd4bb6..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/views/splashscreen/LoadingTask.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.views.splashscreen; - -import org.evergreen.android.R; -import org.evergreen.android.accountAccess.AccountAccess; -import org.evergreen.android.accountAccess.SessionNotFoundException; -import org.evergreen.android.globals.GlobalConfigs; -import org.evergreen_ils.auth.Const; - -import android.accounts.Account; -import android.accounts.AccountManager; -import android.accounts.AccountManagerFuture; -import android.app.Activity; -import android.os.Bundle; -import android.util.Log; - -/** This is basically the same as an AsyncTask, except that it uses - * a Thread. Starting with HONEYCOMB, tasks are executed on a single thread and the 2nd - * AsyncTask doesn't start until the first finishes. - * - * @author kenstir - * - */ -public class LoadingTask { - private final String TAG = LoadingTask.class.getName(); - - public static final String TASK_OK = "OK"; - - public interface LoadingTaskListener { - void onPreExecute(); - void onProgressUpdate(String value); - void onPostExecute(String result); - } - - // This is the listener that will be told when this task is finished - private final LoadingTaskListener mListener; - private Activity mCallingActivity; - private AccountManager mAccountManager; - - public LoadingTask(LoadingTaskListener listener, Activity callingActivity) { - this.mListener = listener; - this.mCallingActivity = callingActivity; - mAccountManager = AccountManager.get(callingActivity); - } - - public void execute() { - Log.d(TAG, "execute>"); - final Thread t = new Thread(new Runnable() { - @Override - public void run() { - final String result = doInBackground(); - mCallingActivity.runOnUiThread(new Runnable() { - @Override - public void run() { - onPostExecute(result); - } - }); - } - }, TAG); - onPreExecute(); - t.start(); - } - - protected void publishProgress(final String progress) { - mCallingActivity.runOnUiThread(new Runnable() { - @Override - public void run() { - onProgressUpdate(progress); - } - }); - } - - //TODO: share some of this code with ScheduledIntentService.onHandleIntent - protected String doInBackground() { - final String tag ="doInBackground> "; - final String accountType = mCallingActivity.getString(R.string.ou_account_type); - Log.d(TAG, tag); - try { - Log.d(TAG, tag+"Loading resources"); - publishProgress("Loading resources"); - GlobalConfigs.getGlobalConfigs(mCallingActivity); // loads IDL - - Log.d(TAG, tag+"Signing in"); - publishProgress("Signing in"); - - AccountManagerFuture future = mAccountManager.getAuthTokenByFeatures(accountType, Const.AUTHTOKEN_TYPE, null, mCallingActivity, null, null, null, null); - Bundle bnd = future.getResult(); - Log.d(TAG, tag+"bnd="+bnd); - String auth_token = bnd.getString(AccountManager.KEY_AUTHTOKEN); - String account_name = bnd.getString(AccountManager.KEY_ACCOUNT_NAME); - Log.d(TAG, tag+"account_name="+account_name+" token="+auth_token); - if (account_name == null) - return "no account"; - - Log.d(TAG, tag+"Starting session"); - publishProgress("Starting session"); - AccountAccess ac = AccountAccess.getAccountAccess(GlobalConfigs.httpAddress); - - // auth token zen: try once and if it fails, invalidate the token and try again - boolean haveSession = false; - boolean retry = false; - try { - haveSession = ac.retrieveSession(auth_token, true); - } catch (SessionNotFoundException e) { - mAccountManager.invalidateAuthToken(accountType, auth_token); - retry = true; - } - if (retry) { - final Account account = new Account(account_name, accountType); - future = mAccountManager.getAuthToken(account, Const.AUTHTOKEN_TYPE, null, mCallingActivity, null, null); - bnd = future.getResult(); - Log.d(TAG, tag+"bnd="+bnd); - auth_token = bnd.getString(AccountManager.KEY_AUTHTOKEN); - account_name = bnd.getString(AccountManager.KEY_ACCOUNT_NAME); - Log.d(TAG, tag+"account_name="+account_name+" token="+auth_token); - if (account_name == null) - return "no account"; - haveSession = ac.retrieveSession(auth_token, true); - } - if (!haveSession) - return "no session"; - - Log.d(TAG, tag+"Retrieving bookbags"); - publishProgress("Retrieving bookbags"); - ac.retrieveBookbags(); - - return TASK_OK; - } catch (Exception e) { - Log.d(TAG, tag+"Caught exception", e); - String s = e.getMessage(); - if (s == null) s = "Cancelled"; - Log.d(TAG, tag+"returning "+s); - return s; - } - } - - protected void onPreExecute() { - Log.d(TAG, "onPreExecute> "); - mListener.onPreExecute(); - } - - protected void onProgressUpdate(String s) { - Log.d(TAG, "onProgressUpdate> "+s); - mListener.onProgressUpdate(s); - } - - protected void onPostExecute(String result) { - Log.d(TAG, "onPostExecute> "+result); - mListener.onPostExecute(result); - } -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen/android/views/splashscreen/SplashActivity.java b/Open-ILS/src/Android/core/src/org/evergreen/android/views/splashscreen/SplashActivity.java deleted file mode 100644 index c5de354ebe..0000000000 --- a/Open-ILS/src/Android/core/src/org/evergreen/android/views/splashscreen/SplashActivity.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (C) 2012 Evergreen Open-ILS - * @author Daniel-Octavian Rizea - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * or the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be usefull, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - * - */ -package org.evergreen.android.views.splashscreen; - -import org.evergreen.android.R; -import org.evergreen.android.globals.GlobalConfigs; -import org.evergreen.android.searchCatalog.SearchCatalogListView; -import org.evergreen.android.views.ApplicationPreferences; -import org.evergreen.android.views.splashscreen.LoadingTask.LoadingTaskListener; - -import android.app.Activity; -import android.app.AlertDialog; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.preference.PreferenceManager; -import android.text.TextUtils; -import android.util.Log; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; -import android.widget.ProgressBar; -import android.widget.TextView; -import org.evergreen_ils.auth.Const; - -public class SplashActivity extends Activity implements LoadingTaskListener { - - private static String TAG = "SplashActivity"; - private TextView mProgressText; - private Context mContext; - private ProgressBar mProgressBar; - private AlertDialog mAlertDialog; - private Button mRetryButton; - //private SharedPreferences prefs; - private LoadingTask mTask; - private static boolean mInitialized; - - public static boolean isAppInitialized() - { - return mInitialized; - } - - /** android may choose to initialize the app at a non-MAIN activity if the - * app crashed or for other reasons. In these cases we want to force sane - * initialization via the SplashActivity. - * - * used in all activity class's onCreate() like so: - * - * if (!SplashActivity.isInitialized) { - * SplashActivity.restartApp(this); - * return; - * } - * - * - * @param a - */ - public static void restartApp(Activity a) - { - Log.d(TAG, "restartApp> Restarting SplashActivity"); - final Intent i = new Intent(a, SplashActivity.class); - i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - a.startActivity(i); - a.finish(); - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_splash); - - this.mContext = this; - - // make sure default values are set up for preferences - PreferenceManager.setDefaultValues(this, R.xml.preferences, false); - - mProgressText = (TextView) findViewById(R.id.action_in_progress); - mProgressBar = (ProgressBar) findViewById(R.id.activity_splash_progress_bar); - mRetryButton = (Button) findViewById(R.id.activity_splash_retry_button); - Log.d(TAG, "onCreate>"); - mRetryButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - startTask(); - } - }); - - GlobalConfigs.httpAddress = getString(R.string.ou_library_url); - startTask(); - } - - protected void startTask() { - Log.d(TAG, "startTask> task="+mTask); - if (mTask != null) - return; - mTask = new LoadingTask(this, this); - mTask.execute(); - } - - @Override - protected void onStop() { - super.onStop(); - if(mAlertDialog != null) { - mAlertDialog.dismiss(); - } - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - Log.d(TAG, "onActivityResult> "+requestCode+" "+resultCode); - } - - private void startApp() { - mInitialized = true; - Intent intent = new Intent(SplashActivity.this, SearchCatalogListView.class); - startActivity(intent); - finish(); - } - - @Override - public void onPreExecute() { - mRetryButton.setVisibility(View.GONE); - mProgressBar.setVisibility(View.VISIBLE); - } - - @Override - public void onProgressUpdate(String value) { - Log.d(TAG, "onProgressUpdate> "+value); - mProgressText.setText(value); - } - - @Override - public void onPostExecute(String result) { - Log.d(TAG, "onPostExecute> "+result); - mTask = null; - Log.d(TAG, "progressbar...gone"); - mProgressBar.setVisibility(View.GONE); - if (TextUtils.equals(result, LoadingTask.TASK_OK)) { - Log.d(TAG, "startApp"); - startApp(); - } else { - String extra_text; - if (!TextUtils.isEmpty(result)) - extra_text = "...Failed:\n" + result; - else - extra_text = "...Cancelled"; - Log.d(TAG, "progresstext += "+extra_text); - mProgressText.setText(mProgressText.getText() + extra_text); - Log.d(TAG, "retrybutton...visible"); - mRetryButton.setVisibility(View.VISIBLE); - } - } -} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/AccountAccess.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/AccountAccess.java new file mode 100644 index 0000000000..ea2b8c3a6e --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/AccountAccess.java @@ -0,0 +1,1218 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.accountAccess; + +import java.io.IOException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.*; + +import android.accounts.*; +import android.app.Activity; +import android.os.Bundle; +import android.os.Looper; +import android.text.TextUtils; +import android.util.Log; +import org.evergreen_ils.R; +import org.evergreen_ils.accountAccess.bookbags.BookBag; +import org.evergreen_ils.accountAccess.bookbags.BookBagItem; +import org.evergreen_ils.accountAccess.checkout.CircRecord; +import org.evergreen_ils.accountAccess.fines.FinesRecord; +import org.evergreen_ils.accountAccess.holds.HoldRecord; +import org.evergreen_ils.globals.Utils; +import org.evergreen_ils.searchCatalog.RecordInfo; +import org.evergreen_ils.auth.Const; +import org.opensrf.net.http.HttpConnection; +import org.opensrf.util.OSRFObject; + +import android.net.ConnectivityManager; + +/** + * The Class AuthenticateUser. Singleton class + */ +public class AccountAccess { + + public static String SERVICE_AUTH = "open-ils.auth"; + + /** The METHOD Auth init. */ + public static String METHOD_AUTH_INIT = "open-ils.auth.authenticate.init"; + + /** The METHOD Auth complete. */ + public static String METHOD_AUTH_COMPLETE = "open-ils.auth.authenticate.complete"; + + /** The METHOD Auth session retrieve. */ + public static String METHOD_AUTH_SESSION_RETRV = "open-ils.auth.session.retrieve"; + + public static String SERVICE_ACTOR = "open-ils.actor"; + public static String SERVICE_CIRC = "open-ils.circ"; + public static String SERVICE_SEARCH = "open-ils.search"; + public static String SERVICE_SERIAL = "open-ils.serial"; + public static String SERVICE_FIELDER = "open-ils.fielder"; + + /** The METHOD_FETCH_CHECKED_OUT_SUM description : for a given user returns a a structure of circulation objects sorted by out, overdue, lost, claims_returned, long_overdue; A list of ID's returned for each type : "out":[id1,id2,...] @returns: { "out":[id 's],"claims_returned":[],"long_overdue":[],"overdue":[],"lost":[] } */ + public static String METHOD_FETCH_CHECKED_OUT_SUM = "open-ils.actor.user.checked_out"; + + /** The METHOD_FETCH_NON_CAT_CIRCS description : for a given user, returns an id-list of non-cataloged circulations that are considered open for now. A circ is open if circ time + circ duration (based on type) is > than now @returns: Array of non-catalogen circ IDs, event or error */ + public static String METHOD_FETCH_NON_CAT_CIRCS = "open-ils.circ.open_non_cataloged_circulation.user"; + + /** The METHOD_FETCH_CIRC_BY_ID description : Retrieves a circ object by ID. @returns : "circ" class. Fields of interest : renewal_remaining, due_date */ + public static String METHOD_FETCH_CIRC_BY_ID = "open-ils.circ.retrieve"; + + /** The METHOD_FETCH_MODS_FROM_COPY description : used to return info. @returns : mvr class OSRF Object. Fields of interest : title, author */ + public static String METHOD_FETCH_MODS_FROM_COPY = "open-ils.search.biblio.mods_from_copy"; + + /** The METHOD_FETCH_COPY description : used to return info for a PRE_CATALOGED object. @returns : acp class OSRF Object. Fields of interest : dummy_title, dummy_author */ + public static String METHOD_FETCH_COPY = "open-ils.search.asset.copy.retrieve"; + + /** The METHOD_RENEW_CIRC description : used to renew a circulation object. @returnes : acn, acp, circ, mus, mbts */ + public static String METHOD_RENEW_CIRC = "open-ils.circ.renew"; + + // Used for Holds Tab + + /** The METHOD_FETCH_HOLDS. @returns: List of "ahr" OSPFObject . Fields of interest : pickup_lib */ + public static String METHOD_FETCH_HOLDS = "open-ils.circ.holds.retrieve"; + + /** The METHOD_FETCH_ORG_SETTINGS description : retrieves a setting from the organization unit. @returns : returns the requested value of the setting */ + public static String METHOD_FETCH_ORG_SETTINGS = "open-ils.actor.ou_setting.ancestor_default"; + + /** The METHOD_FETCH_MRMODS. */ + // if holdtype == M return mvr OSRFObject + public static String METHOD_FETCH_MRMODS = "open-ils.search.biblio.metarecord.mods_slim.retrieve"; + // if holdtype == T return mvr OSRFObject + /** The METHO d_ fetc h_ rmods. */ + public static String METHOD_FETCH_RMODS = "open-ils.search.biblio.record.mods_slim.retrieve"; + // if hold type V + /** The METHO d_ fetc h_ volume. */ + public static String METHOD_FETCH_VOLUME = "open-ils.search.asset.call_number.retrieve"; + // if hold type I + /** The METHO d_ fetc h_ issuance. */ + public static String METHOD_FETCH_ISSUANCE = "open-ils.serial.issuance.pub_fleshed.batch.retrieve"; + + /** The METHO d_ fetc h_ hol d_ status. */ + public static String METHOD_FETCH_HOLD_STATUS = "open-ils.circ.hold.queue_stats.retrieve"; + + /** The METHOD_UPDATE_HOLD description : Updates the specified hold. If session user != hold user then session user must have UPDATE_HOLD permissions @returns : hold_is on success, event or error on failure */ + public static String METHOD_UPDATE_HOLD = "open-ils.circ.hold.update"; + + /** The METHOD_CANCEL_HOLD description : Cancels the specified hold. session user != hold user must have CANCEL_HOLD permissions. @returns : 1 on success, event or error on failure */ + public static String METHOD_CANCEL_HOLD = "open-ils.circ.hold.cancel"; + + /** The METHOD_VERIFY_HOLD_POSSIBLE description :. @returns : hashmap with "success" : 1 field or */ + public static String METHOD_VERIFY_HOLD_POSSIBLE = "open-ils.circ.title_hold.is_possible"; + + /** The METHOD_CREATE_HOLD description :. @returns : hash with messages : "success" : 1 field or */ + public static String METHOD_CREATE_HOLD = "open-ils.circ.holds.create"; + + // Used for Fines + + /** The METHODS_FETCH_FINES_SUMMARY description :. @returns: "mous" OSRFObject. fields: balance_owed, total_owed, total_paid */ + public static String METHOD_FETCH_FINES_SUMMARY = "open-ils.actor.user.fines.summary"; + + /** The METHOD_FETCH_TRANSACTIONS description: For a given user retrieves a list of fleshed transactions. List of objects, each object is a hash containing : transaction, circ, record @returns : array of objects, must investigate */ + public static String METHOD_FETCH_TRANSACTIONS = "open-ils.actor.user.transactions.have_charge.fleshed"; + + /** The METHOD_FETCH_MONEY_BILLING description :. */ + public static String METHOD_FETCH_MONEY_BILLING = "open-ils.circ.money.billing.retrieve.all"; + + // Used for book bags + /** The METHOD_FLESH_CONTAINERS description : Retrieves all un-fleshed buckets by class assigned to a given user VIEW_CONTAINER permissions is requestID != owner ID. @returns : array of "cbreb" OSRFObjects */ + public static String METHOD_FLESH_CONTAINERS = "open-ils.actor.container.retrieve_by_class.authoritative"; + + /** The METHOD_FLESH_PUBLIC_CONTAINER description : array of contaoners correspondig to a id. @returns : array of "crebi" OSRF objects (content of bookbag, id's of elements to get more info) */ + public static String METHOD_FLESH_PUBLIC_CONTAINER = "open-ils.actor.container.flesh"; + + /** The METHO d_ containe r_ delete. */ + public static String METHOD_CONTAINER_DELETE = "open-ils.actor.container.item.delete"; + + /** The METHO d_ containe r_ create. */ + public static String METHOD_CONTAINER_CREATE = "open-ils.actor.container.create"; + + /** The METHO d_ containe r_ ite m_ create. */ + public static String METHOD_CONTAINER_ITEM_CREATE = "open-ils.actor.container.item.create"; + + /** The METHO d_ containe r_ ful l_ delete. */ + public static String METHOD_CONTAINER_FULL_DELETE = "open-ils.actor.container.full_delete"; + + /** The book bags. */ + private ArrayList bookBags = new ArrayList(); + + /** The conn. */ + public HttpConnection conn; + + /** The http address. */ + private String httpAddress = "http://ulysses.calvin.edu"; + + /** The TAG. */ + private final String TAG = AccountAccess.class.getName(); + + /** + * The auth token. Sent with every request that needs authentication + * */ + private String authToken = null; + + /** The cm. */ + private ConnectivityManager cm = null; + + /** The auth time. */ + private Integer authTime = null; + + /** The user id. */ + private Integer userID = null; + + /** home library ID. */ + private Integer homeLibraryID = null; + + private boolean haveSession; + + /** The user name. */ + public static String userName = null; + + /** Whether we have ever established a session **/ + + /** The account access. */ + private static AccountAccess accountAccess = null; + + /** + * Instantiates a new authenticate user. + * + * @param httpAddress the http address + */ + private AccountAccess(String httpAddress) { + + Log.d(TAG, "AccountAccess ctor: " + httpAddress); + this.httpAddress = httpAddress; + + try { + // configure the connection + Log.d(TAG, "Connection with " + httpAddress); + conn = new HttpConnection(httpAddress + "/osrf-gateway-v1"); + + } catch (Exception e) { + Log.d(TAG, "Exception in establishing connection", e); + } + + } + + /** + * Gets the account access. + * + * @param httpAddress the http address + * @return the account access + */ + public static AccountAccess getAccountAccess(String httpAddress) { + + if (accountAccess == null) { + accountAccess = new AccountAccess(httpAddress); + } + if (!httpAddress.equals(accountAccess.httpAddress)) + accountAccess.updateHttpAddress(httpAddress); + + return accountAccess; + } + + // the object must be initialized before + /** + * Gets the account access. + * + * @return the account access + */ + public static AccountAccess getAccountAccess() { + return accountAccess; + } + + public Integer getHomeLibraryID() { + return homeLibraryID; + } + + public void setHomeLibraryID(Integer homeLibraryID) { + this.homeLibraryID = homeLibraryID; + } + + /* + * Change the Http conn to a new library address + */ + /** + * Update http address. + * + * @param httpAddress the http address + */ + public void updateHttpAddress(String httpAddress) { + Log.d(TAG, "update http address of account access to " + + httpAddress); + try { + // configure the connection + this.httpAddress = httpAddress; + Log.d(TAG, "Connection with " + httpAddress); + conn = new HttpConnection(httpAddress + "/osrf-gateway-v1"); + + } catch (Exception e) { + System.err.println("Exception in establishing connection " + + e.getMessage()); + } + } + + /** + * Md5. + * + * @param s + * the s + * @return the string + */ + private String md5(String s) { + try { + // Create MD5 Hash + MessageDigest digest = java.security.MessageDigest + .getInstance("MD5"); + digest.update(s.getBytes()); + byte messageDigest[] = digest.digest(); + + // Create Hex String + StringBuffer hexString = new StringBuffer(); + for (int i = 0; i < messageDigest.length; i++) { + String hex = Integer.toHexString(0xFF & messageDigest[i]); + if (hex.length() == 1) { + // could use a for loop, but we're only dealing with a + // single byte + hexString.append('0'); + } + hexString.append(hex); + } + return hexString.toString(); + + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + + return ""; + } + + /** + * Retrieve session. + * @throws SessionNotFoundException + */ + public boolean retrieveSession(String auth_token, boolean force) throws SessionNotFoundException { + + if (!force && this.haveSession && this.authToken.equals(auth_token)) + return true; + this.haveSession = false; + this.authToken = auth_token; + + Object resp = Utils.doRequest(conn, SERVICE_AUTH, METHOD_AUTH_SESSION_RETRV, authToken, new Object[] {authToken}); + if (resp != null) { + OSRFObject au = (OSRFObject) resp; + userID = au.getInt("id"); + homeLibraryID = au.getInt("home_ou"); + userName = au.getString("usrname"); + //email = au.getString("email"); + this.haveSession = true; + } + return this.haveSession; + } + + public static boolean runningOnUIThread() { + return (Looper.myLooper() == Looper.getMainLooper()); + } + + /** invalidate current auth token and get a new one + * + * @param activity + * @return true if auth successful + */ + public boolean reauthenticate(Activity activity) throws SessionNotFoundException, AuthenticatorException, OperationCanceledException, IOException { + boolean ok = false; + final AccountManager am = AccountManager.get(activity); + final String accountType = activity.getString(R.string.ou_account_type); + final Account account = new Account(userName, accountType); + am.invalidateAuthToken(accountType, authToken); + haveSession = false; + authToken = null; + if (runningOnUIThread()) + return false; + Bundle b = am.getAuthToken(account, Const.AUTHTOKEN_TYPE, null, activity, null, null).getResult(); + final String new_authToken = b.getString(AccountManager.KEY_AUTHTOKEN); + if (TextUtils.isEmpty(new_authToken)) + return false; + return retrieveSession(new_authToken, true); + } + + // ------------------------Checked Out Items Section + // -------------------------// + + /** + * Gets the items checked out. + * + * @return the items checked out + * @throws SessionNotFoundException the session not found exception + */ + public ArrayList getItemsCheckedOut() + throws SessionNotFoundException { + + ArrayList circRecords = new ArrayList(); + + Object resp = Utils.doRequest(conn, SERVICE_ACTOR, + METHOD_FETCH_CHECKED_OUT_SUM, authToken, new Object[] { + authToken, userID }); + if (resp == null) + return circRecords; + Map resp_map = ((Map) resp); + + if (resp_map.get("out") != null) { + List out_id = (List) resp_map.get("out"); + for (int i = 0; i < out_id.size(); i++) { + OSRFObject circ = retrieveCircRecord(out_id.get(i)); + CircRecord circRecord = new CircRecord(circ, CircRecord.OUT, + Integer.parseInt(out_id.get(i))); + fetchInfoForCheckedOutItem(circ.getInt("target_copy"), circRecord); + circRecords.add(circRecord); + } + } + + if (resp_map.get("overdue") != null) { + List overdue_id = (List) resp_map.get("overdue"); + for (int i = 0; i < overdue_id.size(); i++) { + OSRFObject circ = retrieveCircRecord(overdue_id.get(i)); + CircRecord circRecord = new CircRecord(circ, CircRecord.OVERDUE, + Integer.parseInt(overdue_id.get(i))); + fetchInfoForCheckedOutItem(circ.getInt("target_copy"), circRecord); + circRecords.add(circRecord); + } + } + + /* Other fields returned by the request; apparently not used in OPAC + resp_map.get("claims_returned"); + resp_map.get("long_overdue") + resp_map.get("lost"); + */ + + Collections.sort(circRecords, new Comparator() { + @Override + public int compare(CircRecord lhs, CircRecord rhs) { + return lhs.getDueDate().compareTo(rhs.getDueDate()); + } + }); + + return circRecords; + } + + /* + * Retrieves the Circ record + * + * @param : target_copy from circ + * + * @returns : "circ" OSRFObject + */ + /** + * Retrieve circ record. + * + * @param id the id + * @return the oSRF object + * @throws SessionNotFoundException the session not found exception + */ + private OSRFObject retrieveCircRecord(String id) + throws SessionNotFoundException { + + OSRFObject circ = (OSRFObject) Utils.doRequest(conn, SERVICE_CIRC, + METHOD_FETCH_CIRC_BY_ID, authToken, new Object[] { + authToken, id }); + return circ; + } + + /* + * Fetch info for Checked Out Items It uses two methods : + * open-ils.search.biblio.mods_from_copy or in case of pre-cataloged records + * it uses open-ils.search.asset.copy.retriev Usefull info : title and + * author (for acp : dummy_title, dummy_author) + */ + /** + * Fetch info for checked out item. + * + * @param target_copy the target_copy + * @param circRecord the circ record + * @return the oSRF object + */ + private OSRFObject fetchInfoForCheckedOutItem(Integer target_copy, + CircRecord circRecord) { + + if (target_copy == null) + return null; + + OSRFObject result; + Log.d(TAG, "Mods from copy"); + OSRFObject info_mvr = fetchModsFromCopy(target_copy); + // if title or author not inserted, request acp with copy_target + result = info_mvr; + OSRFObject info_acp = null; + + // the logic to establish mvr or acp is copied from the opac + if (info_mvr.getString("title") == null + || info_mvr.getString("author") == null) { + Log.d(TAG, "Asset"); + info_acp = fetchAssetCopy(target_copy); + result = info_acp; + circRecord.acp = info_acp; + circRecord.circ_info_type = CircRecord.ACP_OBJ_TYPE; + } else { + circRecord.mvr = info_mvr; + circRecord.circ_info_type = CircRecord.MVR_OBJ_TYPE; + } + return result; + } + + /** + * Fetch mods from copy. + * + * @param target_copy the target_copy + * @return the oSRF object + */ + private OSRFObject fetchModsFromCopy(Integer target_copy) { + + // sync request + OSRFObject mvr = (OSRFObject) Utils.doRequest(conn, SERVICE_SEARCH, + METHOD_FETCH_MODS_FROM_COPY, cm, new Object[] { target_copy }); + + return mvr; + } + + /** + * Fetch asset copy. + * + * @param target_copy the target_copy + * @return the oSRF object + */ + private OSRFObject fetchAssetCopy(Integer target_copy) { + + OSRFObject acp = (OSRFObject) Utils.doRequest(conn, SERVICE_SEARCH, + METHOD_FETCH_COPY, cm, new Object[] { target_copy }); + + return acp; + } + + /* + * Method used to renew a circulation record based on target_copy_id Returns + * many objects, don't think they are needed + */ + /** + * Renew circ. + * + * @param target_copy the target_copy + * @throws MaxRenewalsException the max renewals exception + * @throws ServerErrorMessage the server error message + * @throws SessionNotFoundException the session not found exception + */ + public void renewCirc(Integer target_copy) throws MaxRenewalsException, + ServerErrorMessage, SessionNotFoundException { + + HashMap complexParam = new HashMap(); + complexParam.put("patron", this.userID); + complexParam.put("copyid", target_copy); + complexParam.put("opac_renewal", 1); + + Object a_lot = (Object) Utils.doRequest(conn, SERVICE_CIRC, + METHOD_RENEW_CIRC, authToken, new Object[] { authToken, + complexParam }); + + Map resp = (Map) a_lot; + + if (resp.get("textcode") != null && !resp.get("textcode").equals("SUCCESS")) { + if (resp.get("textcode").equals("MAX_RENEWALS_REACHED")) + throw new MaxRenewalsException(); + throw new ServerErrorMessage(resp.get("desc").toString()); + } + + } + + // ------------------------Holds Section + // --------------------------------------// + + /** + * Fetch org settings. + * + * @param org_id the org_id + * @param setting the setting + * @return the object + * @throws SessionNotFoundException the session not found exception + */ + public Object fetchOrgSettings(Integer org_id, String setting) + throws SessionNotFoundException { + + OSRFObject response = (OSRFObject) Utils + .doRequest(conn, SERVICE_ACTOR, METHOD_FETCH_ORG_SETTINGS, cm, + new Object[] { org_id, setting }); + return response; + + } + + /** + * Gets the holds. + * + * @return the holds + * @throws SessionNotFoundException the session not found exception + */ + public List getHolds() throws SessionNotFoundException { + + ArrayList holds = new ArrayList(); + + // fields of interest : expire_time + List listHoldsAhr = null; + + Object resp = Utils.doRequest(conn, SERVICE_CIRC, METHOD_FETCH_HOLDS, + authToken, new Object[] { authToken, userID }); + if (resp == null) { + Log.d(TAG, "Result: null"); + return holds; + } + + listHoldsAhr = (List) resp; + + for (int i = 0; i < listHoldsAhr.size(); i++) { + // create hold item + HoldRecord hold = new HoldRecord(listHoldsAhr.get(i)); + // get title + fetchHoldTitleInfo(listHoldsAhr.get(i), hold); + + // get status + fetchHoldStatus(listHoldsAhr.get(i), hold); + + holds.add(hold); + } + return holds; + } + + /* + * hold target type : M - metarecord T - record V - volume I - issuance C - + * copy P - pat + */ + + /** + * Fetch hold title info. + * + * @param holdArhObject the hold arh object + * @param hold the hold + * @return the object + */ + private Object fetchHoldTitleInfo(OSRFObject holdArhObject, HoldRecord hold) { + + String holdType = (String) holdArhObject.get("hold_type"); + + String method = null; + + Object response; + OSRFObject holdInfo = null; + if (holdType.equals("T") || holdType.equals("M")) { + + if (holdType.equals("M")) + method = METHOD_FETCH_MRMODS; + if (holdType.equals("T")) + method = METHOD_FETCH_RMODS; + holdInfo = (OSRFObject) Utils.doRequest(conn, SERVICE_SEARCH, + method, cm, new Object[] { holdArhObject.get("target") }); + + // Log.d(TAG, "Hold here " + holdInfo); + hold.title = ((OSRFObject) holdInfo).getString("title"); + hold.author = ((OSRFObject) holdInfo).getString("author"); + hold.recordInfo = new RecordInfo((OSRFObject) holdInfo); + try { + hold.types_of_resource = ((List) holdInfo + .get("types_of_resource")).get(0).toString(); + } catch (Exception e) { + System.err.println("Can't get types of resurce type" + + e.getMessage()); + } + ; + } else { + // multiple objects per hold ???? + holdInfo = holdFetchObjects(holdArhObject, hold); + + } + return holdInfo; + } + + /** + * Hold fetch objects. + * + * @param hold the hold + * @param holdObj the hold obj + * @return the oSRF object + */ + private OSRFObject holdFetchObjects(OSRFObject hold, HoldRecord holdObj) { + + String type = (String) hold.get("hold_type"); + + Log.d(TAG, "Hold Type " + type); + if (type.equals("C")) { + + /* + * steps asset.copy'->'asset.call_number'->'biblio.record_entry' or, + * in IDL ids, acp->acn->bre + */ + + // fetch_copy + OSRFObject copyObject = fetchAssetCopy(hold.getInt("target")); + // fetch_volume from copyObject.call_number field + Integer call_number = copyObject.getInt("call_number"); + + if (call_number != null) { + + OSRFObject volume = (OSRFObject) Utils.doRequest(conn, + SERVICE_SEARCH, METHOD_FETCH_VOLUME, cm, + new Object[] { copyObject.getInt("call_number") }); + // in volume object : record + Integer record = volume.getInt("record"); + + // part label + holdObj.part_label = volume.getString("label"); + + Log.d(TAG, "Record " + record); + OSRFObject holdInfo = (OSRFObject) Utils.doRequest(conn, + SERVICE_SEARCH, METHOD_FETCH_RMODS, cm, + new Object[] { record }); + + holdObj.title = holdInfo.getString("title"); + holdObj.author = holdInfo.getString("author"); + holdObj.recordInfo = new RecordInfo((OSRFObject) holdInfo); + try { + holdObj.types_of_resource = ((List) holdInfo + .get("types_of_resource")).get(0).toString(); + } catch (Exception e) { + System.err.println("Can't get types of resurce type" + + e.getMessage()); + } + } + + return copyObject; + } else if (type.equals("V")) { + // must test + + // fetch_volume + OSRFObject volume = (OSRFObject) Utils.doRequest(conn, + SERVICE_SEARCH, METHOD_FETCH_VOLUME, cm, + new Object[] { hold.getInt("target") }); + // in volume object : record + + // in volume object : record + Integer record = volume.getInt("record"); + + // part label + holdObj.part_label = volume.getString("label"); + + Log.d(TAG, "Record " + record); + OSRFObject holdInfo = (OSRFObject) Utils.doRequest(conn, + SERVICE_SEARCH, METHOD_FETCH_RMODS, cm, + new Object[] { record }); + + holdObj.title = holdInfo.getString("title"); + holdObj.author = holdInfo.getString("author"); + holdObj.recordInfo = new RecordInfo((OSRFObject) holdInfo); + try { + holdObj.types_of_resource = ((List) holdInfo + .get("types_of_resource")).get(0).toString(); + } catch (Exception e) { + System.err.println("Can't get types of resurce type" + + e.getMessage()); + } + } else if (type.equals("I")) { + OSRFObject issuance = (OSRFObject) Utils.doRequest(conn, + SERVICE_SERIAL, METHOD_FETCH_ISSUANCE, cm, + new Object[] { hold.getInt("target") }); + // TODO + + } else if (type.equals("P")) { + HashMap param = new HashMap(); + + param.put("cache", 1); + + ArrayList fieldsList = new ArrayList(); + fieldsList.add("label"); + fieldsList.add("record"); + + param.put("fields", fieldsList); + HashMap queryParam = new HashMap(); + // PART_ID use "target field in hold" + queryParam.put("id", hold.getInt("target")); + param.put("query", queryParam); + + // returns [{record:id, label=part label}] + + List part = (List) Utils.doRequest(conn, + SERVICE_FIELDER, "open-ils.fielder.bmp.atomic", cm, + new Object[] { param }); + + Map partObj = (Map) part.get(0); + + Integer recordID = (Integer) partObj.get("record"); + String part_label = (String) partObj.get("label"); + + OSRFObject holdInfo = (OSRFObject) Utils.doRequest(conn, + SERVICE_SEARCH, METHOD_FETCH_RMODS, cm, + new Object[] { recordID }); + + holdObj.part_label = part_label; + holdObj.title = holdInfo.getString("title"); + holdObj.author = holdInfo.getString("author"); + holdObj.recordInfo = new RecordInfo((OSRFObject) holdInfo); + try { + holdObj.types_of_resource = ((List) holdInfo + .get("types_of_resource")).get(0).toString(); + } catch (Exception e) { + System.err.println("Can't get types of resurce type" + + e.getMessage()); + } + } + + return null; + } + + /** + * Fetch hold status. + * + * @param hold the hold + * @param holdObj the hold obj + * @throws SessionNotFoundException the session not found exception + */ + public void fetchHoldStatus(OSRFObject hold, HoldRecord holdObj) + throws SessionNotFoundException { + + Integer hold_id = hold.getInt("id"); + // MAP : potential_copies, status, total_holds, queue_position, + // estimated_wait + Object resp = Utils.doRequest(conn, SERVICE_CIRC, + METHOD_FETCH_HOLD_STATUS, authToken, new Object[] { + authToken, hold_id }); + + Map map = (Map)resp; + holdObj.status = map.get("status"); + holdObj.potentialCopies = map.get("potential_copies"); + holdObj.estimatedWaitInSeconds = map.get("estimated_wait"); + holdObj.queuePosition = map.get("queue_position"); + holdObj.totalHolds = map.get("total_holds"); + } + + /** + * Cancel hold. + * + * @param hold the hold + * @return true, if successful + * @throws SessionNotFoundException the session not found exception + */ + public boolean cancelHold(OSRFObject hold) throws SessionNotFoundException { + + Integer hold_id = hold.getInt("id"); + + Object response = Utils.doRequest(conn, SERVICE_CIRC, + METHOD_CANCEL_HOLD, authToken, new Object[] { authToken, + hold_id }); + + // delete successful + if (response.toString().equals("1")) + return true; + + return false; + + } + + /** + * Update hold. + * + * @param ahr the ahr + * @param pickup_lib the pickup_lib + * @param suspendHold the suspend hold + * @param expire_time the expire_time + * @param thaw_date the thaw_date + * @return the object + * @throws SessionNotFoundException the session not found exception + */ + public Object updateHold(OSRFObject ahr, Integer pickup_lib, + boolean suspendHold, String expire_time, String thaw_date) + throws SessionNotFoundException { + // TODO verify that object is correct passed to the server + + ahr.put("pickup_lib", pickup_lib); + ahr.put("expire_time", expire_time); + // frozen set, what this means ? + ahr.put("frozen", suspendHold); + // only if it is frozen + ahr.put("thaw_date", thaw_date); + + Object response = Utils.doRequest(conn, SERVICE_CIRC, + METHOD_UPDATE_HOLD, authToken, new Object[] { authToken, + ahr }); + + return response; + } + + /** + * Creates the hold. + * + * @param recordID the record id + * @param pickup_lib the pickup_lib + * @param email_notify the email_notify + * @param phone_notify the phone_notify + * @param phone the phone + * @param suspendHold the suspend hold + * @param expire_time the expire_time + * @param thaw_date the thaw_date + * @return the string[] + * @throws SessionNotFoundException the session not found exception + */ + public String[] createHold(Integer recordID, Integer pickup_lib, + boolean email_notify, boolean phone_notify, String phone, + boolean suspendHold, String expire_time, String thaw_date) + throws SessionNotFoundException { + + OSRFObject ahr = new OSRFObject("ahr"); + ahr.put("target", recordID); + ahr.put("usr", userID); + ahr.put("requestor", userID); + + // TODO + // only gold type 'T' for now + ahr.put("hold_type", "T"); + ahr.put("pickup_lib", pickup_lib); // pick-up lib + ahr.put("phone_notify", phone); + ahr.put("email_notify", email_notify); + ahr.put("expire_time", expire_time); + // frozen set, what this means ? + ahr.put("frozen", suspendHold); + // only if it is frozen + ahr.put("thaw_date", thaw_date); + + // extra parameters (not mandatory for hold creation) + + Object response = Utils.doRequest(conn, SERVICE_CIRC, + METHOD_CREATE_HOLD, authToken, new Object[] { authToken, + ahr }); + + String[] resp = new String[3]; + // if we can get hold ID then we return true + try { + + Integer id = Integer.parseInt(response.toString()); + if (id > -1) + resp[0] = "true"; + + } catch (Exception e) { + + List respErrorMessage = (List) response; + + Object map = respErrorMessage.get(0); + resp[0] = "false"; + + resp[1] = ((Map) map).get("textcode"); + resp[2] = ((Map) map).get("desc"); + } + + Log.d(TAG, "Result " + resp[1] + " " + resp[2]); + + // else we return false + return resp; + } + + // ?? return boolean + /** + * Checks if is hold possible. + * + * @param pickup_lib the pickup_lib + * @param recordID the record id + * @return the object + * @throws SessionNotFoundException the session not found exception + */ + public Object isHoldPossible(Integer pickup_lib, Integer recordID) + throws SessionNotFoundException { + + HashMap mapAsk = getHoldPreCreateInfo(recordID, + pickup_lib); + mapAsk.put("pickup_lib", pickup_lib); + mapAsk.put("hold_type", null); + mapAsk.put("patronid", userID); + mapAsk.put("volume_id", null); + mapAsk.put("issuanceid", null); + mapAsk.put("copy_id", null); + mapAsk.put("depth", 0); + mapAsk.put("part_id", null); + mapAsk.put("holdable_formats", null); + // {"titleid":63,"mrid":60,"volume_id":null,"issuanceid":null,"copy_id":null,"hold_type":"T","holdable_formats":null, + // "patronid":2,"depth":0,"pickup_lib":"8","partid":null} + + Object response = Utils.doRequest(conn, SERVICE_CIRC, + METHOD_VERIFY_HOLD_POSSIBLE, authToken, new Object[] { + authToken, mapAsk }); + + return response; + } + + // return + /** + * Gets the hold pre create info. + * + * @param recordID the record id + * @param pickup_lib the pickup_lib + * @return the hold pre create info + */ + public HashMap getHoldPreCreateInfo(Integer recordID, + Integer pickup_lib) { + + HashMap param = new HashMap(); + + param.put("pickup_lib", pickup_lib); + param.put("record", recordID); + + Map response = (Map) Utils.doRequest(conn, + SERVICE_SEARCH, + "open-ils.search.metabib.record_to_descriptors", cm, + new Object[] { param }); + + Object obj = response.get("metarecord"); + Log.d(TAG, "metarecord="+obj); + Integer metarecordID = Integer.parseInt(obj.toString()); + + HashMap map = new HashMap(); + map.put("titleid", recordID); + map.put("mrid", metarecordID); + + return map; + /* + * Methods to get necessary info on hold + * open-ils.search.metabib.record_to_descriptors + * + * open-ils.search.biblio.record_hold_parts + */ + } + + // ----------------------------Fines + // Summary------------------------------------// + + /** + * Gets the fines summary. + * + * @return the fines summary + * @throws SessionNotFoundException the session not found exception + */ + public float[] getFinesSummary() throws SessionNotFoundException { + + // mous object + OSRFObject finesSummary = (OSRFObject) Utils.doRequest(conn, + SERVICE_ACTOR, METHOD_FETCH_FINES_SUMMARY, authToken, + new Object[] { authToken, userID }); + + float fines[] = new float[3]; + try { + fines[0] = Float.parseFloat(finesSummary.getString("total_owed")); + fines[1] = Float.parseFloat(finesSummary.getString("total_paid")); + fines[2] = Float.parseFloat(finesSummary.getString("balance_owed")); + } catch (Exception e) { + System.err.println("Exception in parsing fines " + e.getMessage()); + } + + return fines; + } + + /** + * Gets the transactions. + * + * @return the transactions + * @throws SessionNotFoundException the session not found exception + */ + public ArrayList getTransactions() + throws SessionNotFoundException { + + ArrayList finesRecords = new ArrayList(); + + Object transactions = Utils.doRequest(conn, SERVICE_ACTOR, + METHOD_FETCH_TRANSACTIONS, authToken, new Object[] { + authToken, userID }); + + // get Array + + List> list = (List>) transactions; + + for (int i = 0; i < list.size(); i++) { + + Map item = list.get(i); + + FinesRecord record = new FinesRecord(item.get("circ"), + item.get("record"), item.get("transaction")); + finesRecords.add(record); + } + + return finesRecords; + } + + // ---------------------------------------Book + // bags-----------------------------------// + + /** + * Retrieve bookbags from the server. + * + * @return the bookbags + * @throws SessionNotFoundException the session not found exception + */ + public boolean retrieveBookbags() throws SessionNotFoundException { + + Object response = Utils.doRequest(conn, SERVICE_ACTOR, + METHOD_FLESH_CONTAINERS, authToken, new Object[] { + authToken, userID, "biblio", "bookbag" }); + + List bookbags = (List) response; + + ArrayList bookBagObj = new ArrayList(); + // in order to refresh bookbags + this.bookBags = bookBagObj; + + if (bookbags == null) + return true; + + for (int i = 0; i < bookbags.size(); i++) { + + BookBag bag = new BookBag(bookbags.get(i)); + getBookbagContent(bag, bookbags.get(i).getInt("id")); + + bookBagObj.add(bag); + } + return true; + } + + public ArrayList getBookbags() { + return this.bookBags; + } + + /** + * Gets the bookbag content. + * + * @param bag the bag + * @param bookbagID the bookbag id + * @return the bookbag content + * @throws SessionNotFoundException the session not found exception + */ + private Object getBookbagContent(BookBag bag, Integer bookbagID) + throws SessionNotFoundException { + + Map map = (Map) Utils.doRequest(conn, + SERVICE_ACTOR, METHOD_FLESH_PUBLIC_CONTAINER, authToken, + new Object[] { authToken, "biblio", bookbagID }); + + List items = new ArrayList(); + + try{ + items = (List) map.get("items"); + + for (int i = 0; i < items.size(); i++) { + + BookBagItem bookBagItem = new BookBagItem(items.get(i)); + + bag.items.add(bookBagItem); + } + + }catch(Exception e){}; + + return items; + } + + /** + * Removes the bookbag item. + * + * @param id the id + * @throws SessionNotFoundException the session not found exception + */ + public void removeBookbagItem(Integer id) throws SessionNotFoundException { + + removeContainer("biblio", id); + + } + + /** + * Creates the bookbag. + * + * @param name the name + * @throws SessionNotFoundException the session not found exception + */ + public void createBookbag(String name) throws SessionNotFoundException { + + OSRFObject cbreb = new OSRFObject("cbreb"); + cbreb.put("btype", "bookbag"); + cbreb.put("name", name); + cbreb.put("pub", false); + cbreb.put("owner", userID); + + createContainer("biblio", cbreb); + } + + /** + * Delete book bag. + * + * @param id the id + * @throws SessionNotFoundException the session not found exception + */ + public void deleteBookBag(Integer id) throws SessionNotFoundException { + + Object response = Utils.doRequest(conn, SERVICE_ACTOR, + METHOD_CONTAINER_FULL_DELETE, authToken, new Object[] { + authToken, "biblio", id }); + } + + /** + * Adds the record to book bag. + * + * @param record_id the record_id + * @param bookbag_id the bookbag_id + * @throws SessionNotFoundException the session not found exception + */ + public void addRecordToBookBag(Integer record_id, Integer bookbag_id) + throws SessionNotFoundException { + + OSRFObject cbrebi = new OSRFObject("cbrebi"); + cbrebi.put("bucket", bookbag_id); + cbrebi.put("target_biblio_record_entry", record_id); + cbrebi.put("id", null); + + Object response = Utils.doRequest(conn, SERVICE_ACTOR, + METHOD_CONTAINER_ITEM_CREATE, authToken, new Object[] { + authToken, "biblio", cbrebi }); + } + + /** + * Removes the container. + * + * @param container the container + * @param id the id + * @throws SessionNotFoundException the session not found exception + */ + private void removeContainer(String container, Integer id) + throws SessionNotFoundException { + + Object response = Utils.doRequest(conn, SERVICE_ACTOR, + METHOD_CONTAINER_DELETE, authToken, new Object[] { + authToken, container, id }); + } + + /** + * Creates the container. + * + * @param container the container + * @param parameter the parameter + * @throws SessionNotFoundException the session not found exception + */ + private void createContainer(String container, Object parameter) + throws SessionNotFoundException { + + Object response = Utils.doRequest(conn, SERVICE_ACTOR, + METHOD_CONTAINER_CREATE, authToken, new Object[] { + authToken, container, parameter }); + } +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/MaxRenewalsException.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/MaxRenewalsException.java new file mode 100644 index 0000000000..25ece60c3b --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/MaxRenewalsException.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.accountAccess; + +public class MaxRenewalsException extends Exception { + + /** + * + */ + private static final long serialVersionUID = 1L; + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/ServerErrorMessage.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/ServerErrorMessage.java new file mode 100644 index 0000000000..057f08dac5 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/ServerErrorMessage.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.accountAccess; + +public class ServerErrorMessage extends Exception { + + /** + * + */ + private static final long serialVersionUID = 3341617529835568018L; + + public String message; + + public ServerErrorMessage(String message) { + this.message = message; + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/SessionNotFoundException.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/SessionNotFoundException.java new file mode 100644 index 0000000000..fed9ea65d4 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/SessionNotFoundException.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.accountAccess; + +public class SessionNotFoundException extends Exception { + + /** + * + */ + private static final long serialVersionUID = 123232L; + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/bookbags/BookBag.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/bookbags/BookBag.java new file mode 100644 index 0000000000..cfea39e0cd --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/bookbags/BookBag.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.accountAccess.bookbags; + +import java.io.Serializable; +import java.util.ArrayList; + +import org.opensrf.util.OSRFObject; + +public class BookBag implements Serializable { + + public int id; + + public String name = null; + + public String description = null; + + public Boolean shared = null; + + public ArrayList items = null; + + public BookBag(OSRFObject object) { + + this.id = object.getInt("id"); + this.name = object.getString("name"); + this.description = object.getString("description"); + this.items = new ArrayList(); + + String pub_visible = object.getString("pub"); + + if (pub_visible.equals("f")) + this.shared = false; + else + this.shared = true; + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/bookbags/BookBagDetails.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/bookbags/BookBagDetails.java new file mode 100644 index 0000000000..c1d9459811 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/bookbags/BookBagDetails.java @@ -0,0 +1,361 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.accountAccess.bookbags; + +import java.util.ArrayList; +import java.util.List; + +import org.evergreen_ils.R; +import org.evergreen_ils.accountAccess.AccountAccess; +import org.evergreen_ils.accountAccess.SessionNotFoundException; +import org.evergreen_ils.searchCatalog.RecordInfo; +import org.evergreen_ils.searchCatalog.SearchCatalog; +import org.evergreen_ils.searchCatalog.SearchCatalogListView; +import org.evergreen_ils.views.AccountScreenDashboard; +import org.evergreen_ils.views.splashscreen.SplashActivity; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.AlertDialog.Builder; +import android.app.ProgressDialog; +import android.app.Service; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.net.ConnectivityManager; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemSelectedListener; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.ListView; +import android.widget.TextView; +import android.widget.Toast; + +public class BookBagDetails extends Activity { + + private final String TAG = BookBagDetails.class.getName(); + + public static final int RESULT_CODE_UPDATE = 1; + + private SearchCatalog search; + + private AccountAccess accountAccess; + + private ListView lv; + + private BookBagItemsArrayAdapter listAdapter = null; + + private ArrayList bookBagItems = null; + + private Context context; + + private ProgressDialog progressDialog; + + private BookBag bookBag; + + private TextView bookbag_name; + + private Button delete_bookbag_button; + + private Button homeButton; + + private Button myAccountButton; + + private TextView headerTitle; + + private Runnable getBookBagsItemsRunnable; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (!SplashActivity.isAppInitialized()) { + SplashActivity.restartApp(this); + return; + } + + setContentView(R.layout.bookbagitem_list); + // header portion actions + homeButton = (Button) findViewById(R.id.action_bar_home_button); + myAccountButton = (Button) findViewById(R.id.my_account_button); + + myAccountButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getApplicationContext(), + AccountScreenDashboard.class); + startActivity(intent); + } + }); + + homeButton.setText(R.string.bookbag_details_title); + homeButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getApplicationContext(), + SearchCatalogListView.class); + startActivity(intent); + } + }); + // end header portion actions + + accountAccess = AccountAccess.getAccountAccess(); + bookBag = (BookBag) getIntent().getSerializableExtra("bookBag"); + + context = this; + search = SearchCatalog + .getInstance((ConnectivityManager) getSystemService(Service.CONNECTIVITY_SERVICE)); + bookbag_name = (TextView) findViewById(R.id.bookbag_name); + delete_bookbag_button = (Button) findViewById(R.id.remove_bookbag); + bookbag_name.setText(bookBag.name); + delete_bookbag_button.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + + final Thread deleteBookbag = new Thread(new Runnable() { + + @Override + public void run() { + + try { + accountAccess.deleteBookBag(bookBag.id); + } catch (SessionNotFoundException e) { + e.printStackTrace(); + } + runOnUiThread(new Runnable() { + @Override + public void run() { + progressDialog.dismiss(); + setResult(RESULT_CODE_UPDATE); + finish(); + } + }); + } + }); + + Builder confirmationDialogBuilder = new AlertDialog.Builder( + context); + confirmationDialogBuilder.setMessage("Delete bookbag?"); + + confirmationDialogBuilder.setNegativeButton( + android.R.string.no, null); + confirmationDialogBuilder.setPositiveButton( + android.R.string.yes, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, + int which) { + + progressDialog = ProgressDialog.show(context, + getResources().getText(R.string.dialog_please_wait), + "Deleting Bookbag"); + deleteBookbag.start(); + } + }); + + confirmationDialogBuilder.create().show(); + + } + }); + + lv = (ListView) findViewById(R.id.bookbagitem_list); + bookBagItems = new ArrayList(); + listAdapter = new BookBagItemsArrayAdapter(context, + R.layout.bookbagitem_list_item, bookBagItems); + lv.setAdapter(listAdapter); + + lv.setOnItemSelectedListener(new OnItemSelectedListener() { + + @Override + public void onItemSelected(AdapterView arg0, View arg1, + int arg2, long arg3) { + + } + + @Override + public void onNothingSelected(AdapterView arg0) { + // TODO Auto-generated method stub + + } + + }); + + getBookBagsItemsRunnable = new Runnable() { + + @Override + public void run() { + + ArrayList records = new ArrayList(); + ArrayList ids = new ArrayList(); + + for (int i = 0; i < bookBag.items.size(); i++) { + ids.add(bookBag.items.get(i).target_copy); + } + records = search.getRecordsInfo(ids); + + for (int i = 0; i < bookBag.items.size(); i++) { + bookBag.items.get(i).recordInfo = records.get(i); + } + + runOnUiThread(new Runnable() { + + @Override + public void run() { + + listAdapter.clear(); + + for (int i = 0; i < bookBag.items.size(); i++) + listAdapter.add(bookBag.items.get(i)); + + progressDialog.dismiss(); + + if (bookBagItems.size() == 0) + Toast.makeText(context, "No circ records", + Toast.LENGTH_LONG); + + listAdapter.notifyDataSetChanged(); + } + }); + + } + }; + + Thread getBookBags = new Thread(getBookBagsItemsRunnable); + + progressDialog = ProgressDialog.show(context, + getResources().getText(R.string.dialog_please_wait), + "Retrieving bookbag data"); + getBookBags.start(); + + } + + class BookBagItemsArrayAdapter extends ArrayAdapter { + private static final String tag = "BookbagArrayAdapter"; + + private TextView title; + private TextView author; + private Button remove; + + private List records = new ArrayList(); + + public BookBagItemsArrayAdapter(Context context, + int textViewResourceId, List objects) { + super(context, textViewResourceId, objects); + this.records = objects; + } + + public int getCount() { + return this.records.size(); + } + + public BookBagItem getItem(int index) { + return this.records.get(index); + } + + public View getView(int position, View convertView, ViewGroup parent) { + View row = convertView; + + // Get item + final BookBagItem record = getItem(position); + + // if it is the right type of view + if (row == null) { + + Log.d(tag, "Starting XML Row Inflation ... "); + LayoutInflater inflater = (LayoutInflater) this.getContext() + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + row = inflater.inflate(R.layout.bookbagitem_list_item, parent, + false); + Log.d(tag, "Successfully completed XML Row Inflation!"); + + } + + title = (TextView) row.findViewById(R.id.bookbagitem_title); + + author = (TextView) row.findViewById(R.id.bookbagitem_author); + + remove = (Button) row.findViewById(R.id.bookbagitem_remove_button); + + title.setText(record.recordInfo.title); + + author.setText(record.recordInfo.author); + + remove.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + + Thread removeItem = new Thread(new Runnable() { + + @Override + public void run() { + + runOnUiThread(new Runnable() { + @Override + public void run() { + progressDialog = ProgressDialog.show(context, + getResources().getText(R.string.dialog_please_wait), + "Removing item"); + } + }); + + try { + accountAccess.removeBookbagItem(record.id); + } catch (SessionNotFoundException e) { + try { + if (accountAccess.reauthenticate(BookBagDetails.this)) + accountAccess.removeBookbagItem(record.id); + } catch (Exception e1) { + } + } + + runOnUiThread(new Runnable() { + @Override + public void run() { + progressDialog.dismiss(); + + Thread getBookBags = new Thread( + getBookBagsItemsRunnable); + setResult(RESULT_CODE_UPDATE); + + bookBag.items.remove(record); + progressDialog = ProgressDialog.show(context, + getResources().getText(R.string.dialog_please_wait), + "Retrieving bookbag data"); + getBookBags.start(); + + } + }); + } + }); + + removeItem.start(); + } + }); + + return row; + } + } +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/bookbags/BookBagItem.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/bookbags/BookBagItem.java new file mode 100644 index 0000000000..6d3712b077 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/bookbags/BookBagItem.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.accountAccess.bookbags; + +import java.io.Serializable; + +import org.evergreen_ils.searchCatalog.RecordInfo; +import org.opensrf.util.OSRFObject; + +public class BookBagItem implements Serializable { + + public int target_copy; + + public int id; + + public RecordInfo recordInfo; + + public BookBagItem(OSRFObject cbrebi) { + + this.target_copy = cbrebi.getInt("target_biblio_record_entry"); + this.id = cbrebi.getInt("id"); + + } +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/bookbags/BookbagsListView.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/bookbags/BookbagsListView.java new file mode 100644 index 0000000000..16b0b42c1c --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/bookbags/BookbagsListView.java @@ -0,0 +1,322 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.accountAccess.bookbags; + +import java.util.ArrayList; +import java.util.List; + +import org.evergreen_ils.R; +import org.evergreen_ils.accountAccess.AccountAccess; +import org.evergreen_ils.accountAccess.SessionNotFoundException; +import org.evergreen_ils.searchCatalog.SearchCatalogListView; +import org.evergreen_ils.views.AccountScreenDashboard; +import org.evergreen_ils.views.splashscreen.SplashActivity; + +import android.app.Activity; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemSelectedListener; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.EditText; +import android.widget.ListView; +import android.widget.TextView; +import android.widget.Toast; + +public class BookbagsListView extends Activity { + + private final String TAG = BookbagsListView.class.getName(); + + private AccountAccess accountAccess = null; + + private ListView lv; + + private BookBagsArrayAdapter listAdapter = null; + + private ArrayList bookBags = null; + + private Context context; + + private ProgressDialog progressDialog; + + private EditText bookbag_name; + + private Button create_bookbag; + + private Runnable getBookbagsRunnable; + + private Button homeButton; + + private Button myAccountButton; + + private TextView headerTitle; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (!SplashActivity.isAppInitialized()) { + SplashActivity.restartApp(this); + return; + } + + setContentView(R.layout.bookbag_list); + + // header portion actions + myAccountButton = (Button) findViewById(R.id.my_account_button); + myAccountButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getApplicationContext(), + AccountScreenDashboard.class); + startActivity(intent); + } + }); + + homeButton = (Button) findViewById(R.id.action_bar_home_button); + homeButton.setText(R.string.bookbag_items_title); + homeButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getApplicationContext(), + SearchCatalogListView.class); + startActivity(intent); + } + }); + // end header portion actions + + context = this; + accountAccess = AccountAccess.getAccountAccess(); + + bookbag_name = (EditText) findViewById(R.id.bookbag_create_name); + create_bookbag = (Button) findViewById(R.id.bookbag_create_button); + lv = (ListView) findViewById(R.id.bookbag_list); + bookBags = new ArrayList(); + listAdapter = new BookBagsArrayAdapter(context, + R.layout.bookbag_list_item, bookBags); + lv.setAdapter(listAdapter); + + lv.setOnItemSelectedListener(new OnItemSelectedListener() { + + @Override + public void onItemSelected(AdapterView arg0, View arg1, + int position, long arg3) { + + Toast.makeText(getApplicationContext(), "Text", + Toast.LENGTH_LONG).show(); + } + + @Override + public void onNothingSelected(AdapterView arg0) { + // TODO Auto-generated method stub + + } + + }); + create_bookbag.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + + final String name = bookbag_name.getText().toString(); + + Thread createBookbag = new Thread(new Runnable() { + @Override + public void run() { + if (name.length() > 1) { + try { + accountAccess.createBookbag(name); + } catch (SessionNotFoundException e) { + try { + if (accountAccess.reauthenticate(BookbagsListView.this)) + accountAccess.createBookbag(name); + } catch (Exception eauth) { + Log.d(TAG, "Exception in reAuth"); + } + } + + runOnUiThread(new Runnable() { + @Override + public void run() { + progressDialog.dismiss(); + } + }); + + Thread getBookBags = new Thread(getBookbagsRunnable); + getBookBags.start(); + } + } + }); + + if (name.length() > 1) { + progressDialog = ProgressDialog.show(context, + getResources().getText(R.string.dialog_please_wait), + "Creating Bookbag"); + createBookbag.start(); + } else + Toast.makeText(context, + "Bookbag name must be at least 2 characters long", + Toast.LENGTH_SHORT).show(); + } + }); + + getBookbagsRunnable = new Runnable() { + + @Override + public void run() { + runOnUiThread(new Runnable() { + @Override + public void run() { + progressDialog = ProgressDialog.show(context, + getResources().getText(R.string.dialog_please_wait), + "Retrieving Bookbag data"); + } + }); + + try { + accountAccess.retrieveBookbags(); + } catch (SessionNotFoundException e) { + try { + if (accountAccess.reauthenticate(BookbagsListView.this)) + accountAccess.retrieveBookbags(); + } catch (Exception eauth) { + Log.d(TAG, "Exception in reAuth"); + } + } + bookBags = accountAccess.getBookbags(); + + runOnUiThread(new Runnable() { + + @Override + public void run() { + listAdapter.clear(); + for (int i = 0; i < bookBags.size(); i++) + listAdapter.add(bookBags.get(i)); + + progressDialog.dismiss(); + + if (bookBags.size() == 0) + Toast.makeText(context, "No data", + Toast.LENGTH_LONG); + + listAdapter.notifyDataSetChanged(); + } + }); + + } + }; + + new Thread(getBookbagsRunnable).start(); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + // TODO Auto-generated method stub + super.onActivityResult(requestCode, resultCode, data); + + switch (resultCode) { + + case BookBagDetails.RESULT_CODE_UPDATE: { + Thread getBookBags = new Thread(getBookbagsRunnable); + getBookBags.start(); + } + break; + + } + } + + class BookBagsArrayAdapter extends ArrayAdapter { + private static final String tag = "BookbagArrayAdapter"; + + private TextView name; + private TextView items; + private CheckBox shared; + private Button detailsButton; + + private List records = new ArrayList(); + + public BookBagsArrayAdapter(Context context, int textViewResourceId, + List objects) { + super(context, textViewResourceId, objects); + this.records = objects; + } + + public int getCount() { + return this.records.size(); + } + + public BookBag getItem(int index) { + return this.records.get(index); + } + + public View getView(int position, View convertView, ViewGroup parent) { + View row = convertView; + + // Get item + final BookBag record = getItem(position); + + // if it is the right type of view + if (row == null) { + + Log.d(tag, "Starting XML Row Inflation ... "); + LayoutInflater inflater = (LayoutInflater) this.getContext() + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + row = inflater.inflate(R.layout.bookbag_list_item, parent, + false); + Log.d(tag, "Successfully completed XML Row Inflation!"); + + } + + name = (TextView) row.findViewById(R.id.bookbag_name); + + items = (TextView) row.findViewById(R.id.bookbag_items); + + shared = (CheckBox) row.findViewById(R.id.bookbag_shared); + + detailsButton = (Button) row.findViewById(R.id.details_button); + + name.setText(record.name + ""); + + items.setText(record.items.size() + ""); + + shared.setChecked(record.shared); + + detailsButton.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + Intent intent = new Intent(context, BookBagDetails.class); + intent.putExtra("bookBag", record); + startActivityForResult(intent, 0); + + } + }); + + return row; + } + } +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/checkout/CircRecord.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/checkout/CircRecord.java new file mode 100644 index 0000000000..8bc68d9540 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/checkout/CircRecord.java @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.accountAccess.checkout; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.evergreen_ils.globals.GlobalConfigs; +import org.opensrf.util.OSRFObject; + +/** + * This is a wrapper class that get the information out for a circ object + * + * @author daniel + * + */ +public class CircRecord { + + public static final int MVR_OBJ_TYPE = 1; + public static final int ACP_OBJ_TYPE = 2; + public static final int UNDEF_OBJ_TYPE = 0; + + public OSRFObject mvr = null; + + public OSRFObject acp = null; + + public OSRFObject circ = null; + + public int circ_info_type = UNDEF_OBJ_TYPE; + + public int circ_type; + + public static final int OUT = 0; + public static final int CLAIMS_RETURNED = 1; + public static final int LONG_OVERDUE = 2; + public static final int OVERDUE = 3; + public static final int LOST = 4; + + public int circ_id = -1; + + private Date circ_due_date = null; + + public CircRecord(OSRFObject circ, OSRFObject mvr, OSRFObject acp, + int circ_type, int circ_id) { + + this.circ = circ; + + // one of the acp or mvr will be null this will determine the circ + // OSRFObject type + this.acp = acp; + this.mvr = mvr; + + if (this.acp != null) + this.circ_info_type = ACP_OBJ_TYPE; + + if (this.mvr != null) + this.circ_info_type = MVR_OBJ_TYPE; + + this.circ_type = circ_type; + this.circ_id = circ_id; + this.circ_due_date = GlobalConfigs.parseDate(circ.getString("due_date")); + } + + public CircRecord(OSRFObject circ, int circ_type, int circ_id) { + this.circ = circ; + this.circ_type = circ_type; + this.circ_id = circ_id; + this.circ_due_date = GlobalConfigs.parseDate(circ.getString("due_date")); + } + + public String getAuthor() { + + String author = null; + + if (this.circ_info_type == MVR_OBJ_TYPE) + author = mvr.getString("author"); + if (this.circ_info_type == ACP_OBJ_TYPE) + author = acp.getString("dummy_author"); + + return author; + } + + public String getDueDate() { + + return circ_due_date.toLocaleString(); + } + + public Date getDueDateObject() { + return circ_due_date; + } + + public String getTitle() { + + String title = null; + + if (this.circ_info_type == MVR_OBJ_TYPE) + title = mvr.getString("title"); + if (this.circ_info_type == ACP_OBJ_TYPE) + title = acp.getString("dummy_title"); + + return title; + } + + public Integer getRenewals() { + + if (circ != null) + return circ.getInt("renewal_remaining"); + + return null; + } + + public Integer getTargetCopy() { + if (circ != null) + return circ.getInt("target_copy"); + + return null; + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/checkout/ItemsCheckOutListView.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/checkout/ItemsCheckOutListView.java new file mode 100644 index 0000000000..312effff44 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/checkout/ItemsCheckOutListView.java @@ -0,0 +1,367 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.accountAccess.checkout; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import android.opengl.Visibility; +import org.evergreen_ils.R; +import org.evergreen_ils.accountAccess.AccountAccess; +import org.evergreen_ils.accountAccess.MaxRenewalsException; +import org.evergreen_ils.accountAccess.ServerErrorMessage; +import org.evergreen_ils.accountAccess.SessionNotFoundException; +import org.evergreen_ils.searchCatalog.SearchCatalogListView; +import org.evergreen_ils.views.AccountScreenDashboard; +import org.evergreen_ils.views.splashscreen.SplashActivity; + +import android.app.Activity; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.ListView; +import android.widget.TextView; +import android.widget.Toast; + +public class ItemsCheckOutListView extends Activity { + + private final String TAG = ItemsCheckOutListView.class.getName(); + + private AccountAccess accountAccess = null; + + private ListView lv; + + private CheckOutArrayAdapter listAdapter = null; + + private ArrayList circRecords = null; + + private Context context; + + private ProgressDialog progressDialog; + + private Button homeButton; + + private Button myAccountButton; + + private TextView headerTitle; + + private TextView itemsNo; + + private Activity thisActivity; + + private TextView overdueItems; + + private Date currentDate; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (!SplashActivity.isAppInitialized()) { + SplashActivity.restartApp(this); + return; + } + + thisActivity = this; + setContentView(R.layout.checkout_list); + setTitle(R.string.checkout_items_title); + + currentDate = new Date(System.currentTimeMillis()); + + // header portion actions + myAccountButton = (Button) findViewById(R.id.my_account_button); + myAccountButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getApplicationContext(), + AccountScreenDashboard.class); + startActivity(intent); + } + }); + + homeButton = (Button) findViewById(R.id.action_bar_home_button); + homeButton.setText(R.string.checkout_items_title); + homeButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getApplicationContext(), + SearchCatalogListView.class); + startActivity(intent); + } + }); + // end header portion actions + + context = this; + itemsNo = (TextView) findViewById(R.id.checkout_items_number); + overdueItems = (TextView) findViewById(R.id.checkout_items_overdue); + accountAccess = AccountAccess.getAccountAccess(); + lv = (ListView) findViewById(R.id.checkout_items_list); + circRecords = new ArrayList(); + listAdapter = new CheckOutArrayAdapter(context, + R.layout.checkout_list_item, circRecords); + lv.setAdapter(listAdapter); + + Thread getCirc = new Thread(new Runnable() { + + @Override + public void run() { + + try { + circRecords = accountAccess.getItemsCheckedOut(); + } catch (SessionNotFoundException e) { + try { + if (accountAccess.reauthenticate(ItemsCheckOutListView.this)) + circRecords = accountAccess.getItemsCheckedOut(); + } catch (Exception eauth) { + Log.d(TAG, "Exception in reauth", eauth); + } + } + + runOnUiThread(new Runnable() { + + @Override + public void run() { + for (int i = 0; i < circRecords.size(); i++) + listAdapter.add(circRecords.get(i)); + + itemsNo.setText(" " + circRecords.size() + " "); + + // find overdue items + int overdueNo = 0; + for (int i = 0; i < circRecords.size(); i++) { + CircRecord circ = circRecords.get(i); + if (circ.getDueDateObject().compareTo(currentDate) < 0) + overdueNo++; + } + overdueItems.setText(" " + overdueNo); + + progressDialog.dismiss(); + + if (circRecords.size() == 0) + Toast.makeText(context, "No records", + Toast.LENGTH_LONG); + + listAdapter.notifyDataSetChanged(); + } + }); + } + }); + + progressDialog = new ProgressDialog(context); + progressDialog.setMessage("Retrieving circulation data"); + progressDialog.show(); + getCirc.start(); + } + + private void dismissProgress() { + if (progressDialog != null && progressDialog.isShowing()) + progressDialog.dismiss(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater menuInflater = getMenuInflater(); + menuInflater.inflate(R.menu.checkout_menu, menu); + return super.onCreateOptionsMenu(menu); + + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + return super.onOptionsItemSelected(item); + } + + class CheckOutArrayAdapter extends ArrayAdapter { + private static final String tag = "CheckoutArrayAdapter"; + + private TextView recordTitle; + private TextView recordAuthor; + private TextView recordDueDate; + private TextView recordRenewals; + private TextView renewButton; + + private List records = new ArrayList(); + + public CheckOutArrayAdapter(Context context, int textViewResourceId, + List objects) { + super(context, textViewResourceId, objects); + this.records = objects; + } + + public int getCount() { + return this.records.size(); + } + + public CircRecord getItem(int index) { + return this.records.get(index); + } + + public View getView(int position, View convertView, ViewGroup parent) { + View row = convertView; + + // Get item + final CircRecord record = getItem(position); + + // if it is the right type of view + if (row == null) { + + Log.d(tag, "Starting XML Row Inflation ... "); + LayoutInflater inflater = (LayoutInflater) this + .getContext().getSystemService( + Context.LAYOUT_INFLATER_SERVICE); + row = inflater.inflate(R.layout.checkout_list_item, parent, + false); + Log.d(tag, "Successfully completed XML Row Inflation!"); + + } + + // Get reference to TextView - title + recordTitle = (TextView) row.findViewById(R.id.checkout_record_title); + + // Get reference to TextView - author + recordAuthor = (TextView) row.findViewById(R.id.checkout_record_author); + + // Get reference to TextView - record Publisher date+publisher + recordDueDate = (TextView) row.findViewById(R.id.checkout_due_date); + + renewButton = (TextView) row.findViewById(R.id.renew_button); + final boolean renewable = record.getRenewals() > 0; + renewButton.setVisibility(renewable ? View.VISIBLE : View.GONE); + renewButton.setEnabled(renewable); + renewButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (!renewable) + return; + Thread renew = new Thread(new Runnable() { + + @Override + public void run() { + boolean refresh = true; + AccountAccess ac = AccountAccess + .getAccountAccess(); + + runOnUiThread(new Runnable() { + @Override + public void run() { + progressDialog = new ProgressDialog(context); + progressDialog.setMessage("Renewing item"); + progressDialog.show(); + } + }); + + try { + ac.renewCirc(record.getTargetCopy()); + } catch (MaxRenewalsException e1) { + runOnUiThread(new Runnable() { + + @Override + public void run() { + progressDialog.dismiss(); + Toast.makeText(context, + "Max renewals reached", + Toast.LENGTH_LONG).show(); + } + }); + + refresh = false; + } catch (ServerErrorMessage error) { + final String errorMessage = error.message; + runOnUiThread(new Runnable() { + + @Override + public void run() { + progressDialog.dismiss(); + Toast.makeText(context, + errorMessage, + Toast.LENGTH_LONG).show(); + } + }); + } catch (SessionNotFoundException e1) { + try { + if (accountAccess.reauthenticate(ItemsCheckOutListView.this)) + ac.renewCirc(record.getTargetCopy()); + } catch (Exception eauth) { + Log.d(TAG, "Exception in reauth", eauth); + } + } + runOnUiThread(new Runnable() { + @Override + public void run() { + Toast.makeText(context, getString(R.string.item_renewed), Toast.LENGTH_SHORT).show(); + } + }); + + if (refresh) { + try { + circRecords = accountAccess.getItemsCheckedOut(); + } catch (SessionNotFoundException e) { + try { + if (accountAccess.reauthenticate(ItemsCheckOutListView.this)) + circRecords = accountAccess.getItemsCheckedOut(); + } catch (Exception eauth) { + Log.d(TAG, "Exception in reauth", eauth); + } + } + + runOnUiThread(new Runnable() { + @Override + public void run() { + listAdapter.clear(); + for (int i = 0; i < circRecords.size(); i++) { + listAdapter.add(circRecords.get(i)); + } + progressDialog.dismiss(); + listAdapter.notifyDataSetChanged(); + } + }); + } + } + }); + + renew.start(); + } + }); + + // set text + recordTitle.setText(record.getTitle()); + recordAuthor.setText(record.getAuthor()); + recordDueDate.setText(getString(R.string.due) + ": " + record.getDueDate()); + Log.d(TAG, "title: " + record.getTitle()); + Log.d(TAG, "author: " + record.getAuthor()); + Log.d(TAG, "due: " + record.getDueDate()); + Log.d(TAG, "renew: " + record.getRenewals()); + + return row; + } + } +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/fines/FinesActivity.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/fines/FinesActivity.java new file mode 100644 index 0000000000..07bd4e25fd --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/fines/FinesActivity.java @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.accountAccess.fines; + +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; + +import org.evergreen_ils.R; +import org.evergreen_ils.accountAccess.AccountAccess; +import org.evergreen_ils.accountAccess.SessionNotFoundException; +import org.evergreen_ils.searchCatalog.SearchCatalogListView; +import org.evergreen_ils.views.AccountScreenDashboard; +import org.evergreen_ils.views.splashscreen.SplashActivity; + +import android.app.Activity; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.ListView; +import android.widget.TextView; + +public class FinesActivity extends Activity { + + private TextView total_owned; + + private TextView total_paid; + + private TextView balance_owed; + + private ListView lv; + + private Runnable getFinesInfo; + + private AccountAccess ac; + + private ProgressDialog progressDialog; + + private OverdueMaterialsArrayAdapter listAdapter; + + private Button homeButton; + + private Button myAccountButton; + + private TextView headerTitle; + + private Context context; + + private DecimalFormat decimalFormater; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (!SplashActivity.isAppInitialized()) { + SplashActivity.restartApp(this); + return; + } + + setContentView(R.layout.fines); + + // header portion actions + myAccountButton = (Button) findViewById(R.id.my_account_button); + myAccountButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getApplicationContext(), + AccountScreenDashboard.class); + startActivity(intent); + } + }); + + homeButton = (Button) findViewById(R.id.action_bar_home_button); + homeButton.setText(R.string.fines_title); + homeButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getApplicationContext(), + SearchCatalogListView.class); + startActivity(intent); + } + }); + // end header portion actions + + decimalFormater = new DecimalFormat("#0.00"); + lv = (ListView) findViewById(R.id.fines_overdue_materials_list); + + total_owned = (TextView) findViewById(R.id.fines_total_owned); + total_paid = (TextView) findViewById(R.id.fines_total_paid); + balance_owed = (TextView) findViewById(R.id.fined_balance_owed); + context = this; + + ac = AccountAccess.getAccountAccess(); + + ArrayList finesRecords = new ArrayList(); + listAdapter = new OverdueMaterialsArrayAdapter(context, + R.layout.fines_list_item, finesRecords); + lv.setAdapter(listAdapter); + + progressDialog = ProgressDialog.show(this, + getResources().getText(R.string.dialog_please_wait), + "Retrieving fines"); + + getFinesInfo = new Runnable() { + @Override + public void run() { + + float[] finesR = null; + try { + finesR = ac.getFinesSummary(); + } catch (SessionNotFoundException e) { + try { + if (ac.reauthenticate(FinesActivity.this)) + finesR = ac.getFinesSummary(); + } catch (Exception e1) { + } + } + + ArrayList frecords = null; + try { + frecords = ac.getTransactions(); + } catch (SessionNotFoundException e) { + try { + if (ac.reauthenticate(FinesActivity.this)) + frecords = ac.getTransactions(); + } catch (Exception e1) { + } + } + + final ArrayList finesRecords = frecords; + final float[] fines = finesR; + runOnUiThread(new Runnable() { + @Override + public void run() { + + listAdapter.clear(); + + for (int i = 0; i < finesRecords.size(); i++) + listAdapter.add(finesRecords.get(i)); + + listAdapter.notifyDataSetChanged(); + + total_owned.setText(decimalFormater.format(fines[0])); + total_paid.setText(decimalFormater.format(fines[1])); + balance_owed.setText(decimalFormater.format(fines[2])); + progressDialog.dismiss(); + } + }); + } + }; + + Thread getFinesTh = new Thread(getFinesInfo); + getFinesTh.start(); + } + + class OverdueMaterialsArrayAdapter extends ArrayAdapter { + private static final String tag = "CheckoutArrayAdapter"; + + private TextView fineTitle; + private TextView fineAuthor; + private TextView fineBalanceOwed; + private TextView fineStatus; + + private List records = new ArrayList(); + + public OverdueMaterialsArrayAdapter(Context context, + int textViewResourceId, List objects) { + super(context, textViewResourceId, objects); + this.records = objects; + } + + public int getCount() { + return this.records.size(); + } + + public FinesRecord getItem(int index) { + return this.records.get(index); + } + + public View getView(int position, View convertView, ViewGroup parent) { + View row = convertView; + + // Get item + final FinesRecord record = getItem(position); + + if (row == null) { + + Log.d(tag, "Starting XML view more infaltion ... "); + LayoutInflater inflater = (LayoutInflater) this.getContext() + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + row = inflater.inflate(R.layout.fines_list_item, parent, false); + Log.d(tag, "Successfully completed XML view more Inflation!"); + + } + // Get reference to TextView - title + fineTitle = (TextView) row.findViewById(R.id.fines_title); + + // Get reference to TextView author + fineAuthor = (TextView) row.findViewById(R.id.fines_author); + + // Get hold status + fineBalanceOwed = (TextView) row + .findViewById(R.id.fines_balance_owed); + + fineStatus = (TextView) row.findViewById(R.id.fines_status); + // set text + + // set raw information + fineTitle.setText(record.title); + fineAuthor.setText(record.author); + fineBalanceOwed.setText(decimalFormater.format(record.balance_owed)); + // status.setText(record.getHoldStatus()); + fineStatus.setText(record.getStatus()); + + return row; + } + } +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/fines/FinesRecord.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/fines/FinesRecord.java new file mode 100644 index 0000000000..538b168458 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/fines/FinesRecord.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.accountAccess.fines; + +import java.util.Date; + +import org.evergreen_ils.globals.GlobalConfigs; +import org.opensrf.util.OSRFObject; + +public class FinesRecord { + + public String title; + + public String author; + + public Date checkoutDate; + + public Date dueDate; + + public Date dateReturned; + + public Double balance_owed; + + private Date checkin_time; + + // types are grocery and circulation + private int type; + + public static int FINE_GROCERY_TYPE = 1; + public static int FINE_CIRCULATION = 2; + + public FinesRecord(OSRFObject circ, OSRFObject mvr_record, + OSRFObject mbts_transaction) { + + if (mbts_transaction.get("xact_type").toString().equals("circulation")) { + + title = mvr_record.getString("title"); + author = mvr_record.getString("author"); + + if (circ.get("checkin_time") != null) { + checkin_time = GlobalConfigs.parseDate(circ + .getString("checkin_time")); + } else + checkin_time = null; + + } else { + // grocery + title = "Grocery billing"; + author = mbts_transaction.getString("last_billing_note"); + + } + + try{ + balance_owed =Double.parseDouble(mbts_transaction.getString("total_owed")); + }catch(Exception e){ + System.err.println("Error in total owed string to double conversion " + e.getMessage()); + } + } + + // if returned or fines still acumulating + public String getStatus() { + + if (checkin_time != null) + return "returned"; + + return "fines accruing"; + + } +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/holds/HoldDetails.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/holds/HoldDetails.java new file mode 100644 index 0000000000..377ab0d514 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/holds/HoldDetails.java @@ -0,0 +1,433 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.accountAccess.holds; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; + +import android.util.Log; +import org.evergreen_ils.R; +import org.evergreen_ils.accountAccess.AccountAccess; +import org.evergreen_ils.accountAccess.SessionNotFoundException; +import org.evergreen_ils.globals.GlobalConfigs; +import org.evergreen_ils.searchCatalog.SearchCatalogListView; +import org.evergreen_ils.views.AccountScreenDashboard; +import org.evergreen_ils.views.splashscreen.SplashActivity; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.AlertDialog.Builder; +import android.app.DatePickerDialog; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Color; +import android.os.Bundle; +import android.text.format.DateFormat; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemSelectedListener; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.CompoundButton.OnCheckedChangeListener; +import android.widget.DatePicker; +import android.widget.EditText; +import android.widget.Spinner; +import android.widget.TextView; +import android.widget.Toast; + +public class HoldDetails extends Activity { + + private final String TAG = HoldDetails.class.getName(); + + public static final int RESULT_CODE_DELETE_HOLD = 5; + + public static final int RESULT_CODE_UPDATE_HOLD = 6; + + public static final int RESULT_CODE_CANCEL = 7; + + private TextView recipient; + + private TextView title; + + private TextView author; + + private TextView physical_description; + + private TextView screen_title; + + private AccountAccess accountAccess; + + private EditText expiration_date; + + private Button updateHold; + + private Button cancelHold; + + private Button back; + + private DatePickerDialog datePicker = null; + + private CheckBox suspendHold; + + private Spinner orgSelector; + + private DatePickerDialog thaw_datePicker = null; + + private EditText thaw_date_edittext; + + private Date expire_date = null; + + private Date thaw_date = null; + + private Context context; + + private int selectedOrgPos = 0; + + public Runnable updateHoldRunnable; + + private ProgressDialog progressDialog; + + private GlobalConfigs globalConfigs; + + private Button homeButton; + + private Button myAccountButton; + + private TextView headerTitle; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (!SplashActivity.isAppInitialized()) { + SplashActivity.restartApp(this); + return; + } + + context = this; + setContentView(R.layout.hold_details); + globalConfigs = GlobalConfigs.getGlobalConfigs(this); + + myAccountButton = (Button) findViewById(R.id.my_account_button); + myAccountButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getApplicationContext(), + AccountScreenDashboard.class); + startActivity(intent); + } + }); + + homeButton = (Button) findViewById(R.id.action_bar_home_button); + homeButton.setText(R.string.hold_details_title); + homeButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getApplicationContext(), + SearchCatalogListView.class); + startActivity(intent); + } + }); + + final HoldRecord record = (HoldRecord) getIntent() + .getSerializableExtra("holdRecord"); + + Log.d(TAG, "Record " + record + " " + record.title + " " + + record.ahr); + + accountAccess = AccountAccess.getAccountAccess(); + + recipient = (TextView) findViewById(R.id.hold_recipient); + title = (TextView) findViewById(R.id.hold_title); + author = (TextView) findViewById(R.id.hold_author); + physical_description = (TextView) findViewById(R.id.hold_physical_description); + cancelHold = (Button) findViewById(R.id.cancel_hold_button); + updateHold = (Button) findViewById(R.id.update_hold_button); + back = (Button) findViewById(R.id.back_button); + suspendHold = (CheckBox) findViewById(R.id.hold_suspend_hold); + orgSelector = (Spinner) findViewById(R.id.hold_pickup_location); + expiration_date = (EditText) findViewById(R.id.hold_expiration_date); + thaw_date_edittext = (EditText) findViewById(R.id.hold_thaw_date); + + recipient.setText(accountAccess.userName); + title.setText(record.title); + author.setText(record.author); + if (record.recordInfo != null) + physical_description + .setText(record.recordInfo.physical_description); + + // set record info + suspendHold.setChecked(record.suspended); + + if (record.thaw_date != null) { + thaw_date = record.thaw_date; + thaw_date_edittext.setText(DateFormat.format("MMMM dd, yyyy", + thaw_date)); + } + if (record.expire_time != null) { + expire_date = record.expire_time; + expiration_date.setText(DateFormat.format("MMMM dd, yyyy", + expire_date)); + } + + // hide edit text + if (record.thaw_date == null) + disableView(thaw_date_edittext); + + Log.d(TAG, record.title + " " + record.author); + + back.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + + cancelHold.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + + Builder confirmationDialogBuilder = new AlertDialog.Builder( + context); + confirmationDialogBuilder + .setMessage(R.string.cancel_hold_dialog_message); + + confirmationDialogBuilder.setNegativeButton( + android.R.string.no, null); + confirmationDialogBuilder.setPositiveButton( + android.R.string.yes, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, + int which) { + + Log.d(TAG, "Remove hold with id" + + record.ahr.getInt("id")); + + progressDialog = ProgressDialog.show(context, + getResources().getText(R.string.dialog_please_wait), + "Canceling hold"); + Thread cancelHoldThread = new Thread( + new Runnable() { + + @Override + public void run() { + + try { + accountAccess + .cancelHold(record.ahr); + } catch (SessionNotFoundException e) { + try { + if (accountAccess.reauthenticate(HoldDetails.this)) + accountAccess + .cancelHold(record.ahr); + } catch (Exception eauth) { + Log.d(TAG, "Exception in reAuth"); + } + } + + runOnUiThread(new Runnable() { + @Override + public void run() { + progressDialog + .dismiss(); + setResult(RESULT_CODE_DELETE_HOLD); + + finish(); + } + }); + } + }); + cancelHoldThread.start(); + + } + }); + confirmationDialogBuilder.create().show(); + + } + }); + + updateHoldRunnable = new Runnable() { + @Override + public void run() { + // update new values + String expire_date_s = null; + String thaw_date_s = null; + if (expire_date != null) + expire_date_s = GlobalConfigs.getStringDate(expire_date); + if (thaw_date != null) + thaw_date_s = GlobalConfigs.getStringDate(thaw_date); + + try { + accountAccess.updateHold(record.ahr, selectedOrgPos, + suspendHold.isChecked(), + expire_date_s, thaw_date_s); + } catch (SessionNotFoundException e) { + try { + if (accountAccess.reauthenticate(HoldDetails.this)) + accountAccess.updateHold(record.ahr, + selectedOrgPos, + suspendHold.isChecked(), expire_date_s, + thaw_date_s); + } catch (Exception eauth) { + Log.d(TAG, "Exception in reAuth"); + } + } + + runOnUiThread(new Runnable() { + @Override + public void run() { + progressDialog.dismiss(); + Toast.makeText(context, "Hold updated", + Toast.LENGTH_SHORT); + setResult(RESULT_CODE_UPDATE_HOLD); + finish(); + } + }); + } + }; + + updateHold.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + progressDialog = ProgressDialog.show(context, + getResources().getText(R.string.dialog_please_wait), + "Updating hold"); + Thread updateHoldThread = new Thread(updateHoldRunnable); + updateHoldThread.start(); + } + }); + + suspendHold.setOnCheckedChangeListener(new OnCheckedChangeListener() { + + @Override + public void onCheckedChanged(CompoundButton buttonView, + boolean isChecked) { + + if (isChecked) { + enableView(thaw_date_edittext); + } else { + disableView(thaw_date_edittext); + } + } + }); + Calendar cal = Calendar.getInstance(); + + datePicker = new DatePickerDialog(this, + new DatePickerDialog.OnDateSetListener() { + + public void onDateSet(DatePicker view, int year, + int monthOfYear, int dayOfMonth) { + + Date chosenDate = new Date(year - 1900, monthOfYear, + dayOfMonth); + expire_date = chosenDate; + CharSequence strDate = DateFormat.format( + "MMMM dd, yyyy", chosenDate); + expiration_date.setText(strDate); + // set current date + } + }, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), + cal.get(Calendar.DAY_OF_MONTH)); + + expiration_date.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + datePicker.show(); + } + }); + + thaw_datePicker = new DatePickerDialog(this, + new DatePickerDialog.OnDateSetListener() { + + public void onDateSet(DatePicker view, int year, + int monthOfYear, int dayOfMonth) { + + Date chosenDate = new Date(year - 1900, monthOfYear, + dayOfMonth); + thaw_date = chosenDate; + CharSequence strDate = DateFormat.format( + "MMMM dd, yyyy", chosenDate); + thaw_date_edittext.setText(strDate); + // set current date + } + }, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), + cal.get(Calendar.DAY_OF_MONTH)); + + thaw_date_edittext.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + thaw_datePicker.show(); + } + }); + + ArrayList list = new ArrayList(); + for (int i = 0; i < globalConfigs.organisations.size(); i++) { + list.add(globalConfigs.organisations.get(i).padding + + globalConfigs.organisations.get(i).name); + + if (globalConfigs.organisations.get(i).id == record.pickup_lib) + selectedOrgPos = i; + } + ArrayAdapter adapter = new ArrayAdapter(this, + R.layout.spinner_layout, list); + orgSelector.setAdapter(adapter); + + orgSelector.setSelection(selectedOrgPos); + + orgSelector.setOnItemSelectedListener(new OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView arg0, View arg1, int ID, + long arg3) { + + selectedOrgPos = ID; + + } + + public void onNothingSelected(android.widget.AdapterView arg0) { + } + }); + } + + public void disableView(View view) { + + // view.setFocusable(false); + view.setFocusable(false); + + view.setBackgroundColor(Color.argb(255, 100, 100, 100)); + // view.setVisibility(View.INVISIBLE); + } + + public void enableView(View view) { + // view.setVisibility(View.VISIBLE); + + view.setFocusableInTouchMode(true); + + view.setBackgroundColor(Color.argb(255, 255, 255, 255)); + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/holds/HoldRecord.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/holds/HoldRecord.java new file mode 100644 index 0000000000..6faf3107ae --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/holds/HoldRecord.java @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.accountAccess.holds; + +import java.io.Serializable; +import java.util.Date; + +import org.evergreen_ils.R; +import org.evergreen_ils.globals.GlobalConfigs; +import org.evergreen_ils.searchCatalog.RecordInfo; +import org.opensrf.util.OSRFObject; +import android.content.res.Resources; + +public class HoldRecord implements Serializable { + + private Integer requestLibID = null; + + private Integer pickupLibID = null; + + public String holdType = null; + // id for target object + public Integer target = null; + public Date expire_time = null; + + public String title = null; + + public String author = null; + + public String types_of_resource; + + // only for P types + public String part_label = null; + + public Integer status = null; + + public Boolean active = null; + + // must also be serializable + public OSRFObject ahr = null; + // record info with more etails + public RecordInfo recordInfo = null; + + public boolean email_notification = false; + + public String phone_notification = null; + + public boolean suspended = false; + + public Date thaw_date; + + public int pickup_lib; + + public Integer potentialCopies; + + public Integer estimatedWaitInSeconds; + + public Integer queuePosition; + + public Integer totalHolds; + + public HoldRecord(OSRFObject ahr) { + + this.target = ahr.getInt("target"); + this.holdType = ahr.getString("hold_type"); + + this.ahr = ahr; + + this.expire_time = GlobalConfigs.parseDate(ahr.getString("expire_time")); + this.thaw_date = GlobalConfigs.parseDate(ahr.getString("thaw_date")); + this.email_notification = GlobalConfigs.parseBoolean(ahr.getString("email_notify")); + this.phone_notification = ahr.getString("phone_notify"); + this.suspended = GlobalConfigs.parseBoolean(ahr.getString("frozen")); + pickup_lib = ahr.getInt("pickup_lib"); + + } + + // Retreive hold status in text + public String getHoldStatus(Resources res) { + // Constants from Holds.pm and logic from hold_status.tt2 + // -1 on error (for now), + // 1 for 'waiting for copy to become available', + // 2 for 'waiting for copy capture', + // 3 for 'in transit', + // 4 for 'arrived', + // 5 for 'hold-shelf-delay' + // 6 for 'canceled' + // 7 for 'suspended' + // 8 for 'captured, on wrong hold shelf' + if (status == 4) { + return "Available"; + } else if (estimatedWaitInSeconds > 0) { + int days = (int)Math.ceil((double)estimatedWaitInSeconds / 86400.0); + return "Estimated wait "+days+" day wait"; + } else if (status == 3 || status == 8) { + return "In Transit"; + } else if (status < 3) { + return "Waiting for copy\n" + + res.getQuantityString(R.plurals.number_of_holds, totalHolds, totalHolds) + " on " + + res.getQuantityString(R.plurals.number_of_copies, potentialCopies, potentialCopies) + + "\n" + + "Queue position: " + queuePosition; + } else { + return ""; + } + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/holds/HoldsListView.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/holds/HoldsListView.java new file mode 100644 index 0000000000..301be4ad81 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/holds/HoldsListView.java @@ -0,0 +1,280 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.accountAccess.holds; + +import java.util.ArrayList; +import java.util.List; + +import org.evergreen_ils.R; +import org.evergreen_ils.accountAccess.AccountAccess; +import org.evergreen_ils.accountAccess.SessionNotFoundException; +import org.evergreen_ils.globals.GlobalConfigs; +import org.evergreen_ils.searchCatalog.ImageDownloader; +import org.evergreen_ils.searchCatalog.SearchCatalogListView; +import org.evergreen_ils.views.AccountScreenDashboard; +import org.evergreen_ils.views.splashscreen.SplashActivity; + +import android.app.Activity; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.TextView; +import org.evergreen_ils.accountAccess.holds.HoldRecord; + +public class HoldsListView extends Activity { + + private final String TAG = HoldsListView.class.getName(); + + private AccountAccess accountAccess = null; + + private ListView lv; + + private HoldsArrayAdapter listAdapter = null; + + private List holdRecords = null; + + private Context context; + + Runnable getHoldsRunnable = null; + + private Button homeButton; + + private Button myAccountButton; + + private TextView headerTitle; + + private TextView holdsNoText; + + private ProgressDialog progressDialog; + + private ImageDownloader imageDownloader; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (!SplashActivity.isAppInitialized()) { + SplashActivity.restartApp(this); + return; + } + + setContentView(R.layout.holds_list); + + // header portion actions + myAccountButton = (Button) findViewById(R.id.my_account_button); + myAccountButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getApplicationContext(), + AccountScreenDashboard.class); + startActivity(intent); + } + }); + + homeButton = (Button) findViewById(R.id.action_bar_home_button); + homeButton.setText(R.string.hold_items_title); + homeButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getApplicationContext(), + SearchCatalogListView.class); + startActivity(intent); + } + }); + // end header portion actions + + holdsNoText = (TextView) findViewById(R.id.holds_number); + + imageDownloader = new ImageDownloader(40, 40, false); + + lv = (ListView) findViewById(R.id.holds_item_list); + context = this; + accountAccess = AccountAccess.getAccountAccess(); + + holdRecords = new ArrayList(); + listAdapter = new HoldsArrayAdapter(context, R.layout.holds_list_item, + holdRecords); + lv.setAdapter(listAdapter); + + getHoldsRunnable = new Runnable() { + @Override + public void run() { + + try { + holdRecords = accountAccess.getHolds(); + } catch (SessionNotFoundException e) { + try { + if (accountAccess.reauthenticate(HoldsListView.this)) + holdRecords = accountAccess.getHolds(); + } catch (Exception eauth) { + Log.d(TAG, "Exception in reauth"); + } + } + + runOnUiThread(new Runnable() { + @Override + public void run() { + listAdapter.clear(); + + for (int i = 0; i < holdRecords.size(); i++) + listAdapter.add(holdRecords.get(i)); + + holdsNoText.setText(" " + listAdapter.getCount()); + progressDialog.dismiss(); + listAdapter.notifyDataSetChanged(); + } + }); + } + }; + + progressDialog = new ProgressDialog(context); + progressDialog.setMessage("Loading holds"); + progressDialog.show(); + + // thread to retrieve holds + Thread getHoldsThread = new Thread(getHoldsRunnable); + getHoldsThread.start(); + + lv.setOnItemClickListener(new OnItemClickListener() { + + @Override + public void onItemClick(AdapterView arg0, View arg1, + int position, long arg3) { + HoldRecord record = (HoldRecord) lv.getItemAtPosition(position); + + Intent intent = new Intent(getApplicationContext(), + HoldDetails.class); + + intent.putExtra("holdRecord", record); + + // doae not matter request code, only result code + startActivityForResult(intent, 0); + } + }); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + // TODO Auto-generated method stub + super.onActivityResult(requestCode, resultCode, data); + + switch (resultCode) { + + case HoldDetails.RESULT_CODE_CANCEL: + // nothing + Log.d(TAG, "Do nothing"); + break; + + case HoldDetails.RESULT_CODE_DELETE_HOLD: + case HoldDetails.RESULT_CODE_UPDATE_HOLD: + // refresh ui + progressDialog = new ProgressDialog(context); + progressDialog.setMessage("Loading holds"); + progressDialog.show(); + // thread to retrieve holds + Thread getHoldsThread = new Thread(getHoldsRunnable); + getHoldsThread.start(); + Log.d(TAG, "Update on result "+resultCode); + break; + } + } + + class HoldsArrayAdapter extends ArrayAdapter { + private static final String tag = "CheckoutArrayAdapter"; + + private TextView holdTitle; + private TextView holdAuthor; + private TextView status; + private ImageView hold_icon; + + private List records = new ArrayList(); + + public HoldsArrayAdapter(Context context, int textViewResourceId, + List objects) { + super(context, textViewResourceId, objects); + this.records = objects; + } + + public int getCount() { + return this.records.size(); + } + + public HoldRecord getItem(int index) { + return this.records.get(index); + } + + public View getView(int position, View convertView, ViewGroup parent) { + View row = convertView; + + // Get item + final HoldRecord record = getItem(position); + + if (row == null) { + + Log.d(tag, "Starting XML view more infaltion ... "); + LayoutInflater inflater = (LayoutInflater) this.getContext() + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + row = inflater.inflate(R.layout.holds_list_item, parent, false); + Log.d(tag, "Successfully completed XML view more Inflation!"); + + } + + hold_icon = (ImageView) row.findViewById(R.id.hold_resource_icon); + + // Get reference to TextView - title + holdTitle = (TextView) row.findViewById(R.id.hold_title); + + // Get reference to TextView author + holdAuthor = (TextView) row.findViewById(R.id.hold_author); + + // Get hold status + status = (TextView) row.findViewById(R.id.hold_status); + + // set text + String imageResourceHref = GlobalConfigs.httpAddress + + GlobalConfigs.hold_icon_address + + record.types_of_resource + ".jpg"; + + if (imageResourceHref.contains(" ")) { + imageResourceHref = imageResourceHref.replace(" ", "%20"); + } + + imageDownloader.download(imageResourceHref, hold_icon); + + // set raw information + holdTitle.setText(record.title); + holdAuthor.setText(record.author); + status.setText(record.getHoldStatus(getResources())); + + return row; + } + } +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/holds/PlaceHold.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/holds/PlaceHold.java new file mode 100644 index 0000000000..8c1ce74caf --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/accountAccess/holds/PlaceHold.java @@ -0,0 +1,394 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.accountAccess.holds; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; + +import android.util.Log; +import org.evergreen_ils.R; +import org.evergreen_ils.accountAccess.AccountAccess; +import org.evergreen_ils.accountAccess.SessionNotFoundException; +import org.evergreen_ils.globals.GlobalConfigs; +import org.evergreen_ils.searchCatalog.RecordInfo; +import org.evergreen_ils.searchCatalog.SearchCatalogListView; +import org.evergreen_ils.views.AccountScreenDashboard; +import org.evergreen_ils.views.splashscreen.SplashActivity; + +import android.app.Activity; +import android.app.DatePickerDialog; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.os.Bundle; +import android.text.format.DateFormat; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemSelectedListener; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.CompoundButton.OnCheckedChangeListener; +import android.widget.DatePicker; +import android.widget.EditText; +import android.widget.Spinner; +import android.widget.TextView; +import android.widget.Toast; + +public class PlaceHold extends Activity { + + private final String TAG = PlaceHold.class.getName(); + + private TextView recipient; + + private TextView title; + + private TextView author; + + private TextView physical_description; + + private TextView screen_title; + + private AccountAccess accountAccess; + + private EditText expiration_date; + + private EditText phone_number; + + private CheckBox phone_notification; + + private CheckBox email_notification; + + private Button placeHold; + + private Button cancel; + + private CheckBox suspendHold; + + private Spinner orgSelector; + + private DatePickerDialog datePicker = null; + + private DatePickerDialog thaw_datePicker = null; + + private EditText thaw_date_edittext; + + private Date expire_date = null; + + private Date thaw_date = null; + + private Runnable placeHoldRunnable; + + private GlobalConfigs globalConfigs = null; + + private int selectedOrgPos = 0; + + private Button homeButton; + + private Button myAccountButton; + + private TextView headerTitle; + + private ProgressDialog progressDialog; + + private Context context; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (!SplashActivity.isAppInitialized()) { + SplashActivity.restartApp(this); + return; + } + + setContentView(R.layout.place_hold); + globalConfigs = GlobalConfigs.getGlobalConfigs(this); + RecordInfo record = (RecordInfo) getIntent().getSerializableExtra( + "recordInfo"); + + myAccountButton = (Button) findViewById(R.id.my_account_button); + myAccountButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getApplicationContext(), + AccountScreenDashboard.class); + startActivity(intent); + } + }); + + homeButton = (Button) findViewById(R.id.action_bar_home_button); + homeButton.setText(R.string.hold_place_title); + homeButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getApplicationContext(), + SearchCatalogListView.class); + startActivity(intent); + } + }); + + context = this; + + accountAccess = AccountAccess.getAccountAccess(); + + recipient = (TextView) findViewById(R.id.hold_recipient); + title = (TextView) findViewById(R.id.hold_title); + author = (TextView) findViewById(R.id.hold_author); + physical_description = (TextView) findViewById(R.id.hold_physical_description); + cancel = (Button) findViewById(R.id.cancel_hold); + placeHold = (Button) findViewById(R.id.place_hold); + expiration_date = (EditText) findViewById(R.id.hold_expiration_date); + phone_notification = (CheckBox) findViewById(R.id.hold_enable_phone_notification); + phone_number = (EditText) findViewById(R.id.hold_contact_telephone); + email_notification = (CheckBox) findViewById(R.id.hold_enable_email_notification); + suspendHold = (CheckBox) findViewById(R.id.hold_suspend_hold); + orgSelector = (Spinner) findViewById(R.id.hold_pickup_location); + thaw_date_edittext = (EditText) findViewById(R.id.hold_thaw_date); + + recipient.setText(accountAccess.userName); + title.setText(record.title); + author.setText(record.author); + physical_description.setText(record.physical_description); + + // hide edit text + disableView(thaw_date_edittext); + disableView(phone_number); + + cancel.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + + final Integer record_id = record.doc_id; + + placeHoldRunnable = new Runnable() { + + @Override + public void run() { + + runOnUiThread(new Runnable() { + @Override + public void run() { + progressDialog = ProgressDialog.show(context, + getResources().getText(R.string.dialog_please_wait), + "Placing hold"); + } + }); + // TODO verify hold possible + + // accountAccess.getHoldPreCreateInfo(record_id, 4); + // accountAccess.isHoldPossible(4, record_id); + + String expire_date_s = null; + String thaw_date_s = null; + if (expire_date != null) + expire_date_s = GlobalConfigs.getStringDate(expire_date); + if (thaw_date != null) + thaw_date_s = GlobalConfigs.getStringDate(thaw_date); + + Log.d(TAG, "date expire: " + expire_date_s + " " + + expire_date); + int selectedOrgID = -1; + if (globalConfigs.organisations.size() > selectedOrgPos) + selectedOrgID = globalConfigs.organisations + .get(selectedOrgPos).id; + + String[] stringResponse = new String[] { "false" }; + try { + stringResponse = accountAccess.createHold(record_id, + selectedOrgID, email_notification.isChecked(), + phone_notification.isChecked(), phone_number + .getText().toString(), suspendHold + .isChecked(), expire_date_s, thaw_date_s); + } catch (SessionNotFoundException e) { + try { + if (accountAccess.reauthenticate(PlaceHold.this)) + stringResponse = accountAccess.createHold( + record_id, selectedOrgID, + email_notification.isChecked(), + phone_notification.isChecked(), + phone_number.getText().toString(), + suspendHold.isChecked(), expire_date_s, + thaw_date_s); + } catch (Exception e1) { + } + } + + final String[] holdPlaced = stringResponse; + + runOnUiThread(new Runnable() { + @Override + public void run() { + progressDialog.dismiss(); + + if (holdPlaced[0].equals("true")) { + Toast.makeText(context, "Hold Succesfully placed", + Toast.LENGTH_LONG).show(); + finish(); + } else + Toast.makeText(context, + "Error in placing hold : " + holdPlaced[2], + Toast.LENGTH_LONG).show(); + + } + }); + } + }; + + placeHold.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + + Thread placeholdThread = new Thread(placeHoldRunnable); + placeholdThread.start(); + } + }); + + phone_notification + .setOnCheckedChangeListener(new OnCheckedChangeListener() { + + @Override + public void onCheckedChanged(CompoundButton buttonView, + boolean isChecked) { + + if (isChecked) { + enableView(phone_number); + } else + disableView(phone_number); + } + }); + + suspendHold.setOnCheckedChangeListener(new OnCheckedChangeListener() { + + @Override + public void onCheckedChanged(CompoundButton buttonView, + boolean isChecked) { + + if (isChecked) { + enableView(thaw_date_edittext); + } else { + disableView(thaw_date_edittext); + } + } + }); + + Calendar cal = Calendar.getInstance(); + + datePicker = new DatePickerDialog(this, + new DatePickerDialog.OnDateSetListener() { + + public void onDateSet(DatePicker view, int year, + int monthOfYear, int dayOfMonth) { + + Date chosenDate = new Date(year - 1900, monthOfYear, + dayOfMonth); + expire_date = chosenDate; + CharSequence strDate = DateFormat.format( + "MMMM dd, yyyy", chosenDate); + expiration_date.setText(strDate); + // set current date + } + }, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), + cal.get(Calendar.DAY_OF_MONTH)); + + expiration_date.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + datePicker.show(); + } + }); + + thaw_datePicker = new DatePickerDialog(this, + new DatePickerDialog.OnDateSetListener() { + + public void onDateSet(DatePicker view, int year, + int monthOfYear, int dayOfMonth) { + + Date chosenDate = new Date(year - 1900, monthOfYear, + dayOfMonth); + thaw_date = chosenDate; + CharSequence strDate = DateFormat.format( + "MMMM dd, yyyy", chosenDate); + thaw_date_edittext.setText(strDate); + // set current date + } + }, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), + cal.get(Calendar.DAY_OF_MONTH)); + + thaw_date_edittext.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + thaw_datePicker.show(); + } + }); + + ArrayList list = new ArrayList(); + for (int i = 0; i < globalConfigs.organisations.size(); i++) { + list.add(globalConfigs.organisations.get(i).padding + + globalConfigs.organisations.get(i).name); + + if (globalConfigs.organisations.get(i).level - 1 == 0) + selectedOrgPos = i; + } + ArrayAdapter adapter = new ArrayAdapter(this, + android.R.layout.simple_spinner_item, list); + orgSelector.setAdapter(adapter); + + orgSelector.setSelection(selectedOrgPos); + + orgSelector.setOnItemSelectedListener(new OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView arg0, View arg1, int ID, + long arg3) { + + selectedOrgPos = ID; + + } + + public void onNothingSelected(android.widget.AdapterView arg0) { + } + }); + } + + public void disableView(View view) { + + // view.setFocusable(false); + view.setFocusable(false); + + view.setBackgroundColor(Color.argb(255, 100, 100, 100)); + // view.setVisibility(View.INVISIBLE); + } + + public void enableView(View view) { + // view.setVisibility(View.VISIBLE); + + view.setFocusableInTouchMode(true); + + view.setBackgroundColor(Color.argb(255, 255, 255, 255)); + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/auth/AuthenticatorActivity.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/auth/AuthenticatorActivity.java index 037452cd74..f43042a15d 100644 --- a/Open-ILS/src/Android/core/src/org/evergreen_ils/auth/AuthenticatorActivity.java +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/auth/AuthenticatorActivity.java @@ -1,7 +1,7 @@ package org.evergreen_ils.auth; import android.preference.PreferenceManager; -import org.evergreen.android.R; +import org.evergreen_ils.R; import org.evergreen_ils.auth.Const; import android.accounts.Account; diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/auth/EvergreenAuthenticator.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/auth/EvergreenAuthenticator.java index b1eef4eb3a..0e32462f57 100644 --- a/Open-ILS/src/Android/core/src/org/evergreen_ils/auth/EvergreenAuthenticator.java +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/auth/EvergreenAuthenticator.java @@ -15,7 +15,7 @@ import org.opensrf.net.http.HttpRequest; import android.content.Context; import android.text.TextUtils; import android.util.Log; -import org.evergreen.android.R; +import org.evergreen_ils.R; public class EvergreenAuthenticator { private final static String TAG = "eg.auth"; diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/CaptureActivity.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/CaptureActivity.java new file mode 100755 index 0000000000..8516c3e039 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/CaptureActivity.java @@ -0,0 +1,212 @@ +package org.evergreen_ils.barcodescan; + +import java.io.IOException; +import java.util.Vector; + +import org.evergreen_ils.R; +import org.evergreen_ils.barcodescan.camera.CameraManager; +import org.evergreen_ils.views.splashscreen.SplashActivity; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Bitmap; +import android.os.Bundle; +import android.os.Handler; +import android.util.Log; +import android.view.Menu; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.view.Window; +import android.view.WindowManager; +import android.widget.Toast; + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.Result; + +public class CaptureActivity extends Activity implements SurfaceHolder.Callback { + + private static final String TAG = CaptureActivity.class.getSimpleName(); + + private ViewfinderView viewfinderView; + + private CaptureActivityHandler handler; + + private CameraManager cameraManager; + private boolean hasSurface; + private Vector decodeFormats; + // private HistoryManager historyManager; + private Result lastResult; + private String characterSet; + public static final int BARCODE_SEARCH = 1; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (!SplashActivity.isAppInitialized()) { + SplashActivity.restartApp(this); + return; + } + + // Remove title bar + this.requestWindowFeature(Window.FEATURE_NO_TITLE); + + // Remove notification bar + this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + + setContentView(R.layout.barcode_scan); + + Log.d("BARCODE","Start application 1"); + Window window = getWindow(); + window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + + // init camera manager + cameraManager = new CameraManager(getApplication()); + hasSurface = false; + handler = null; + + viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view); + + viewfinderView.setCameraManager(cameraManager); + //database = new DBHelper(this); + + Log.d("BARCODE","Start application 2"); + } + + + @Override + public void onResume() { + super.onResume(); + + SurfaceView surfaceView = (SurfaceView) findViewById(R.id.camera_view); + SurfaceHolder surfaceHolder = surfaceView.getHolder(); + if (hasSurface) { + // The activity was paused but not stopped, so the surface still + // exists. Therefore + // surfaceCreated() won't be called, so init the camera here. + initCamera(surfaceHolder); + } else { + // Install the callback and wait for surfaceCreated() to init the + // camera. + surfaceHolder.addCallback(this); + surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); + } + + } + + @Override + protected void onPause() { + super.onPause(); + if (handler != null) { + handler.quitSynchronously(); + handler = null; + } + cameraManager.closeDriver(); + } + + public void surfaceCreated(SurfaceHolder holder) { + if (!hasSurface) { + hasSurface = true; + initCamera(holder); + } + } + + public void surfaceDestroyed(SurfaceHolder holder) { + hasSurface = false; + } + + public void surfaceChanged(SurfaceHolder holder, int format, int width, + int height) { + + } + + private void initCamera(SurfaceHolder surfaceHolder) { + try { + + + cameraManager.openDriver(surfaceHolder); + // Creating the handler starts the preview, which can also throw a + // RuntimeException. + if (handler == null) { + //decodeFormats.addAll(DecodeFormatManager.ONE_D_FORMATS); + handler = new CaptureActivityHandler(this, decodeFormats, + characterSet, cameraManager); + } + } catch (IOException ioe) { + Log.w(TAG, ioe); + displayFrameworkBugMessageAndExit("IOException"); + } catch (RuntimeException e) { + // Barcode Scanner has seen crashes in the wild of this variety: + // java.?lang.?RuntimeException: Fail to connect to camera service + Log.w(TAG, "Unexpected error initializating camera", e); + displayFrameworkBugMessageAndExit("RuntimeException"); + } + } + + public Handler getHandler() { + return handler; + } + + ViewfinderView getViewfinderView() { + return viewfinderView; + } + + + private void displayFrameworkBugMessageAndExit(String info) { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(getString(R.string.ou_app_name)); + builder.setMessage("[" + info + "] " + + getString(R.string.msg_camera_framework_bug)); + builder.setPositiveButton(R.string.button_ok, new FinishListener(this)); + builder.setOnCancelListener(new FinishListener(this)); + builder.show(); + } + + public void drawViewfinder() { + // Draw image result + + viewfinderView.drawViewfinder(); + } + + public void removePoints() { + + } + + + /** + * A valid barcode has been found, so give an indication of success and show the results. + * + * @param rawResult The contents of the barcode. + * @param barcode A greyscale bitmap of the camera data which was decoded. + */ + public void handleDecode(Result rawResult, Bitmap barcode) { + + + /* + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setMessage("Code bar Message : " + rawResult.getText()) + .setCancelable(false) + .setPositiveButton("Yes", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + //restart preview to decode more barcodes + if(handler != null){ + handler.sendEmptyMessage(R.id.restart_preview); + } + } + }); + + AlertDialog alert = builder.create(); + alert.show(); + */ + + //Toast.makeText(this, rawResult.getText(), Toast.LENGTH_LONG).show(); + Log.d("BARCODE","Value"+ rawResult.getText()); + Intent intent = new Intent(); + intent.putExtra("barcodeValue", rawResult.getText()); + setResult(BARCODE_SEARCH, intent); + finish(); + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/CaptureActivityHandler.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/CaptureActivityHandler.java new file mode 100755 index 0000000000..8165cc3638 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/CaptureActivityHandler.java @@ -0,0 +1,125 @@ + +package org.evergreen_ils.barcodescan; + +import java.util.Vector; + +import org.evergreen_ils.R; +import org.evergreen_ils.barcodescan.camera.CameraManager; + +import android.app.Activity; +import android.content.Intent; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.util.Log; + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.Result; + +/** + * This class handles all the messaging which comprises the state machine for capture. +@ + */ +public final class CaptureActivityHandler extends Handler { + + private static final String TAG = CaptureActivityHandler.class.getSimpleName(); + + private final CaptureActivity activity; + private final DecodeThread decodeThread; + private final CameraManager cameraManager; + private State state; + + private enum State { + PREVIEW, + SUCCESS, + DONE + } + + CaptureActivityHandler(CaptureActivity activity, Vector decodeFormats, + String characterSet,CameraManager cameraManager) { + this.activity = activity; + decodeThread = new DecodeThread(activity, decodeFormats, characterSet, + new ViewfinderResultPointCallback(activity.getViewfinderView()), cameraManager); + decodeThread.start(); + state = State.SUCCESS; + + // Start ourselves capturing previews and decoding. + this.cameraManager = cameraManager; + cameraManager.startPreview(); + restartPreviewAndDecode(); + if (state == State.PREVIEW) { + this.cameraManager.requestAutoFocus(this, R.id.auto_focus); + } + + } + @Override + public void handleMessage(Message message) { + if (message.what == R.id.auto_focus) {//Log.d(TAG, "Got auto-focus message"); + // When one auto focus pass finishes, start another. This is the closest thing to + + + } else if (message.what == R.id.decode_succeeded) { + Log.d(TAG, "Got decode succeeded message"); + state = State.SUCCESS; + + + Bundle bundle = message.getData(); + Bitmap barcode = bundle == null ? null : + (Bitmap) bundle.getParcelable(DecodeThread.BARCODE_BITMAP); + + activity.handleDecode((Result) message.obj, barcode); + + + } else if (message.what == R.id.restart_preview) { + restartPreviewAndDecode(); + + + } else if (message.what == R.id.decode_failed) {// We're decoding as fast as possible, so when one decode fails, start another. + state = State.PREVIEW; + cameraManager.requestPreviewFrame(decodeThread.getHandler(), R.id.decode); + activity.removePoints(); + + + } else if (message.what == R.id.return_scan_result) { + Log.d(TAG, "Got return scan result message"); + activity.setResult(Activity.RESULT_OK, (Intent) message.obj); + activity.finish(); + + } else if (message.what == R.id.launch_product_query) { + Log.d(TAG, "Got product query message"); + String url = (String) message.obj; + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); + activity.startActivity(intent); + + } + } + + public void quitSynchronously() { + state = State.DONE; + cameraManager.stopPreview(); + Message quit = Message.obtain(decodeThread.getHandler(), R.id.quit); + quit.sendToTarget(); + try { + decodeThread.join(); + } catch (InterruptedException e) { + // continue + } + + // Be absolutely sure we don't send any queued up messages + removeMessages(R.id.decode_succeeded); + removeMessages(R.id.decode_failed); + } + + private void restartPreviewAndDecode() { + if (state == State.SUCCESS) { + state = State.PREVIEW; + cameraManager.requestPreviewFrame(decodeThread.getHandler(), R.id.decode); + cameraManager.requestAutoFocus(this, R.id.auto_focus); + activity.drawViewfinder(); + } + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/DecodeFormatManager.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/DecodeFormatManager.java new file mode 100755 index 0000000000..701941b166 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/DecodeFormatManager.java @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2010 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.evergreen_ils.barcodescan; + +import java.util.Arrays; +import java.util.List; +import java.util.Vector; +import java.util.regex.Pattern; + +import android.content.Intent; +import android.net.Uri; +import com.google.zxing.BarcodeFormat; + +final class DecodeFormatManager { + + private static final Pattern COMMA_PATTERN = Pattern.compile(","); + + static final Vector PRODUCT_FORMATS; + static final Vector ONE_D_FORMATS; + static final Vector QR_CODE_FORMATS; + static final Vector DATA_MATRIX_FORMATS; + static { + PRODUCT_FORMATS = new Vector(5); + PRODUCT_FORMATS.add(BarcodeFormat.UPC_A); + PRODUCT_FORMATS.add(BarcodeFormat.UPC_E); + PRODUCT_FORMATS.add(BarcodeFormat.EAN_13); + PRODUCT_FORMATS.add(BarcodeFormat.EAN_8); + PRODUCT_FORMATS.add(BarcodeFormat.RSS_14); + ONE_D_FORMATS = new Vector(PRODUCT_FORMATS.size() + 4); + ONE_D_FORMATS.addAll(PRODUCT_FORMATS); + ONE_D_FORMATS.add(BarcodeFormat.CODE_39); + ONE_D_FORMATS.add(BarcodeFormat.CODE_93); + ONE_D_FORMATS.add(BarcodeFormat.CODE_128); + ONE_D_FORMATS.add(BarcodeFormat.ITF); + QR_CODE_FORMATS = new Vector(1); + QR_CODE_FORMATS.add(BarcodeFormat.QR_CODE); + DATA_MATRIX_FORMATS = new Vector(1); + DATA_MATRIX_FORMATS.add(BarcodeFormat.DATA_MATRIX); + } + + private DecodeFormatManager() {} + + static Vector parseDecodeFormats(Intent intent) { + List scanFormats = null; + String scanFormatsString = intent.getStringExtra(Intents.Scan.FORMATS); + if (scanFormatsString != null) { + scanFormats = Arrays.asList(COMMA_PATTERN.split(scanFormatsString)); + } + return parseDecodeFormats(scanFormats, intent.getStringExtra(Intents.Scan.MODE)); + } + + static Vector parseDecodeFormats(Uri inputUri) { + List formats = inputUri.getQueryParameters(Intents.Scan.FORMATS); + if (formats != null && formats.size() == 1 && formats.get(0) != null){ + formats = Arrays.asList(COMMA_PATTERN.split(formats.get(0))); + } + return parseDecodeFormats(formats, inputUri.getQueryParameter(Intents.Scan.MODE)); + } + + private static Vector parseDecodeFormats(Iterable scanFormats, + String decodeMode) { + if (scanFormats != null) { + Vector formats = new Vector(); + try { + for (String format : scanFormats) { + formats.add(BarcodeFormat.valueOf(format)); + } + return formats; + } catch (IllegalArgumentException iae) { + // ignore it then + } + } + if (decodeMode != null) { + if (Intents.Scan.PRODUCT_MODE.equals(decodeMode)) { + return PRODUCT_FORMATS; + } + if (Intents.Scan.QR_CODE_MODE.equals(decodeMode)) { + return QR_CODE_FORMATS; + } + if (Intents.Scan.DATA_MATRIX_MODE.equals(decodeMode)) { + return DATA_MATRIX_FORMATS; + } + if (Intents.Scan.ONE_D_MODE.equals(decodeMode)) { + return ONE_D_FORMATS; + } + } + return null; + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/DecodeHandler.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/DecodeHandler.java new file mode 100755 index 0000000000..713de87ca0 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/DecodeHandler.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2010 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.evergreen_ils.barcodescan; + +import java.util.Hashtable; +import org.evergreen_ils.R; +import org.evergreen_ils.barcodescan.camera.CameraManager; + +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.util.Log; + +import com.google.zxing.BinaryBitmap; +import com.google.zxing.DecodeHintType; +import com.google.zxing.MultiFormatReader; +import com.google.zxing.ReaderException; +import com.google.zxing.Result; +import com.google.zxing.common.HybridBinarizer; + +final class DecodeHandler extends Handler { + + private static final String TAG = DecodeHandler.class.getSimpleName(); + + //Activity used for communication with her's handle + private final CaptureActivity activity; + private CameraManager cameraManager; + //Reader used to decode + private final MultiFormatReader multiFormatReader; + + //running state of this decode thread + private boolean running = true; + + DecodeHandler(CaptureActivity activity, Hashtable hints, CameraManager cameraManager) { + multiFormatReader = new MultiFormatReader(); + multiFormatReader.setHints(hints); + this.activity = activity; + this.cameraManager = cameraManager; + } + + /** + * Method handles messages obtained + * + */ + @Override + public void handleMessage(Message message) { + if (!running) { + return; + //if thread is not running do nothing + } + if (message.what == R.id.decode) { + decode((byte[]) message.obj, message.arg1, message.arg2); + + } else if (message.what == R.id.quit) {//quit, set running false + running = false; + Looper.myLooper().quit(); + + } + } + + + /** + * Decode the data within the viewfinder rectangle, and time how long it took. For efficiency, + * reuse the same reader objects from one decode to the next. + * + * @param data The YUV preview frame. + * @param width The width of the preview frame. + * @param height The height of the preview frame. + */ + private void decode(byte[] data, int width, int height) { + long start = System.currentTimeMillis(); + Result rawResult = null; + PlanarYUVLuminanceSource source = cameraManager.buildLuminanceSource(data, width, height); + if (source != null) { + BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); + try { + rawResult = multiFormatReader.decodeWithState(bitmap); + } catch (ReaderException re) { + // continue + } finally { + multiFormatReader.reset(); + } + } + + Handler handler = activity.getHandler(); + if (rawResult != null) { + // Don't log the barcode contents for security. + long end = System.currentTimeMillis(); + Log.d(TAG, "Found barcode in " + (end - start) + " ms"); + if (handler != null) { + Message message = Message.obtain(handler, R.id.decode_succeeded, rawResult); + Bundle bundle = new Bundle(); + bundle.putParcelable(DecodeThread.BARCODE_BITMAP, source.renderCroppedGreyscaleBitmap()); + message.setData(bundle); + message.sendToTarget(); + } + } else { + if (handler != null) { + Message message = Message.obtain(handler, R.id.decode_failed); + message.sendToTarget(); + } + } + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/DecodeThread.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/DecodeThread.java new file mode 100755 index 0000000000..07c8cc2286 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/DecodeThread.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2008 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.evergreen_ils.barcodescan; + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.DecodeHintType; +import com.google.zxing.ResultPointCallback; + +import android.content.SharedPreferences; +import android.os.Handler; +import android.os.Looper; +import android.preference.PreferenceManager; + +import java.util.Hashtable; +import java.util.Vector; +import java.util.concurrent.CountDownLatch; + +import org.evergreen_ils.barcodescan.camera.CameraManager; + +/** + * This thread does all the heavy lifting of decoding the images. + * + * @author dswitkin@google.com (Daniel Switkin) + */ +final class DecodeThread extends Thread { + + public static final String BARCODE_BITMAP = "barcode_bitmap"; + + private final CaptureActivity activity; + private final Hashtable hints; + private Handler handler; + private final CountDownLatch handlerInitLatch; + private CameraManager cameraManager; + DecodeThread(CaptureActivity activity, + Vector decodeFormats, + String characterSet, + ResultPointCallback resultPointCallback, CameraManager cameraManager) { + + this.activity = activity; + handlerInitLatch = new CountDownLatch(1); + this.cameraManager = cameraManager; + hints = new Hashtable(3); + + + + // The prefs can't change while the thread is running, so pick them up once here. + if (decodeFormats == null || decodeFormats.isEmpty()) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity); + decodeFormats = new Vector(); + if (prefs.getBoolean(PreferencesActivity.KEY_DECODE_1D, true)) { + decodeFormats.addAll(DecodeFormatManager.ONE_D_FORMATS); + } + /* + if (prefs.getBoolean(PreferencesActivity.KEY_DECODE_QR, true)) { + decodeFormats.addAll(DecodeFormatManager.QR_CODE_FORMATS); + } + if (prefs.getBoolean(PreferencesActivity.KEY_DECODE_DATA_MATRIX, true)) { + decodeFormats.addAll(DecodeFormatManager.DATA_MATRIX_FORMATS); + } + */ + } + hints.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormats); + + if (characterSet != null) { + hints.put(DecodeHintType.CHARACTER_SET, characterSet); + } + hints.put(DecodeHintType.NEED_RESULT_POINT_CALLBACK, resultPointCallback); + } + + Handler getHandler() { + try { + handlerInitLatch.await(); + } catch (InterruptedException ie) { + // continue? + } + return handler; + } + + @Override + public void run() { + Looper.prepare(); + handler = new DecodeHandler(activity, hints, cameraManager); + handlerInitLatch.countDown(); + Looper.loop(); + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/FinishListener.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/FinishListener.java new file mode 100755 index 0000000000..da7f6e8442 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/FinishListener.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2010 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.evergreen_ils.barcodescan; + +import android.app.Activity; +import android.content.DialogInterface; + +/** + * Simple listener used to exit the app in a few cases. + * + * @author Sean Owen + */ +public final class FinishListener + implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener, Runnable { + + private final Activity activityToFinish; + + public FinishListener(Activity activityToFinish) { + this.activityToFinish = activityToFinish; + } + + public void onCancel(DialogInterface dialogInterface) { + run(); + } + + public void onClick(DialogInterface dialogInterface, int i) { + run(); + } + + public void run() { + activityToFinish.finish(); + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/Functions.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/Functions.java new file mode 100755 index 0000000000..f7e11f5b0d --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/Functions.java @@ -0,0 +1,56 @@ +package org.evergreen_ils.barcodescan; + +import android.content.Context; +import android.graphics.Color; +import android.widget.TextView; +import android.widget.Toast; + +/** + * + * @author George Oprina + * + * 08.06.2011 + */ + +public class Functions { + + // makes toast length short + public static void makeToast(String s, Context c) { + CharSequence text = s; + int duration = Toast.LENGTH_SHORT; + + Toast toast = Toast.makeText(c, text, duration); + toast.show(); + } + + // makes toast selectable length + public static void makeToast(String s, Context c, int length) { + CharSequence text = s; + int duration = Toast.LENGTH_SHORT; + + if (length == 1) + duration = Toast.LENGTH_LONG; + + Toast toast = Toast.makeText(c, text, duration); + toast.show(); + } + + // makes text view from string + public static TextView makeTextView(String s, Context c) { + TextView text = new TextView(c); + text.setBackgroundColor(Color.WHITE); + text.setText(s); + text.setTextColor(Color.BLACK); + return text; + } + + // thread sleep + public static void sleep(int msec) { + try { + Thread.sleep(msec); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/Intents.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/Intents.java new file mode 100755 index 0000000000..04b010ec0e --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/Intents.java @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2008 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.evergreen_ils.barcodescan; + +/** + * This class provides the constants to use when sending an Intent to Barcode Scanner. + * These strings are effectively API and cannot be changed. + * + * @author dswitkin@google.com (Daniel Switkin) + */ +public final class Intents { + private Intents() { + } + + public static final class Scan { + /** + * Send this intent to open the Barcodes app in scanning mode, find a barcode, and return + * the results. + */ + public static final String ACTION = "com.google.zxing.client.android.SCAN"; + + /** + * By default, sending Scan.ACTION will decode all barcodes that we understand. However it + * may be useful to limit scanning to certain formats. Use Intent.putExtra(MODE, value) with + * one of the values below. + * + * Setting this is effectively shorthand for setting explicit formats with {@link #FORMATS}. + * It is overridden by that setting. + */ + public static final String MODE = "SCAN_MODE"; + + /** + * Decode only UPC and EAN barcodes. This is the right choice for shopping apps which get + * prices, reviews, etc. for products. + */ + public static final String PRODUCT_MODE = "PRODUCT_MODE"; + + /** + * Decode only 1D barcodes. + */ + public static final String ONE_D_MODE = "ONE_D_MODE"; + + /** + * Decode only QR codes. + */ + public static final String QR_CODE_MODE = "QR_CODE_MODE"; + + /** + * Decode only Data Matrix codes. + */ + public static final String DATA_MATRIX_MODE = "DATA_MATRIX_MODE"; + + /** + * Comma-separated list of formats to scan for. The values must match the names of + * {@link com.google.zxing.BarcodeFormat}s, e.g. {@link com.google.zxing.BarcodeFormat#EAN_13}. + * Example: "EAN_13,EAN_8,QR_CODE" + * + * This overrides {@link #MODE}. + */ + public static final String FORMATS = "SCAN_FORMATS"; + + /** + * @see com.google.zxing.DecodeHintType#CHARACTER_SET + */ + public static final String CHARACTER_SET = "CHARACTER_SET"; + + /** + * Optional parameters to specify the width and height of the scanning rectangle in pixels. + * The app will try to honor these, but will clamp them to the size of the preview frame. + * You should specify both or neither, and pass the size as an int. + */ + public static final String WIDTH = "SCAN_WIDTH"; + public static final String HEIGHT = "SCAN_HEIGHT"; + + /** + * If a barcode is found, Barcodes returns RESULT_OK to onActivityResult() of the app which + * requested the scan via startSubActivity(). The barcodes contents can be retrieved with + * intent.getStringExtra(RESULT). If the user presses Back, the result code will be + * RESULT_CANCELED. + */ + public static final String RESULT = "SCAN_RESULT"; + + /** + * Call intent.getStringExtra(RESULT_FORMAT) to determine which barcode format was found. + * See Contents.Format for possible values. + */ + public static final String RESULT_FORMAT = "SCAN_RESULT_FORMAT"; + + /** + * Call intent.getByteArrayExtra(RESULT_BYTES) to get a {@link byte[]} of raw bytes in the + * barcode, if available. + */ + public static final String RESULT_BYTES = "SCAN_RESULT_BYTES"; + + /** + * Setting this to false will not save scanned codes in the history. + */ + public static final String SAVE_HISTORY = "SAVE_HISTORY"; + + private Scan() { + } + } + + public static final class Encode { + /** + * Send this intent to encode a piece of data as a QR code and display it full screen, so + * that another person can scan the barcode from your screen. + */ + public static final String ACTION = "com.google.zxing.client.android.ENCODE"; + + /** + * The data to encode. Use Intent.putExtra(DATA, data) where data is either a String or a + * Bundle, depending on the type and format specified. Non-QR Code formats should + * just use a String here. For QR Code, see Contents for details. + */ + public static final String DATA = "ENCODE_DATA"; + + /** + * The type of data being supplied if the format is QR Code. Use + * Intent.putExtra(TYPE, type) with one of Contents.Type. + */ + public static final String TYPE = "ENCODE_TYPE"; + + /** + * The barcode format to be displayed. If this isn't specified or is blank, + * it defaults to QR Code. Use Intent.putExtra(FORMAT, format), where + * format is one of Contents.Format. + */ + public static final String FORMAT = "ENCODE_FORMAT"; + + private Encode() { + } + } + + public static final class SearchBookContents { + /** + * Use Google Book Search to search the contents of the book provided. + */ + public static final String ACTION = "com.google.zxing.client.android.SEARCH_BOOK_CONTENTS"; + + /** + * The book to search, identified by ISBN number. + */ + public static final String ISBN = "ISBN"; + + /** + * An optional field which is the text to search for. + */ + public static final String QUERY = "QUERY"; + + private SearchBookContents() { + } + } + + public static final class WifiConnect { + /** + * Internal intent used to trigger connection to a wi-fi network. + */ + public static final String ACTION = "com.google.zxing.client.android.WIFI_CONNECT"; + + /** + * The network to connect to, all the configuration provided here. + */ + public static final String SSID = "SSID"; + + /** + * The network to connect to, all the configuration provided here. + */ + public static final String TYPE = "TYPE"; + + /** + * The network to connect to, all the configuration provided here. + */ + public static final String PASSWORD = "PASSWORD"; + + private WifiConnect() { + } + } + + public static final class Share { + /** + * Give the user a choice of items to encode as a barcode, then render it as a QR Code and + * display onscreen for a friend to scan with their phone. + */ + public static final String ACTION = "com.google.zxing.client.android.SHARE"; + + private Share() { + } + } +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/PlanarYUVLuminanceSource.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/PlanarYUVLuminanceSource.java new file mode 100755 index 0000000000..eba9e946fb --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/PlanarYUVLuminanceSource.java @@ -0,0 +1,142 @@ +/* + * Copyright 2009 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.evergreen_ils.barcodescan; + +import com.google.zxing.LuminanceSource; + +import android.graphics.Bitmap; + +/** + * This object extends LuminanceSource around an array of YUV data returned from the camera driver, + * with the option to crop to a rectangle within the full data. This can be used to exclude + * superfluous pixels around the perimeter and speed up decoding. + * + * It works for any pixel format where the Y channel is planar and appears first, including + * YCbCr_420_SP and YCbCr_422_SP. + * + * @author dswitkin@google.com (Daniel Switkin) + */ +public final class PlanarYUVLuminanceSource extends LuminanceSource { + + private final byte[] yuvData; + private final int dataWidth; + private final int dataHeight; + private final int left; + private final int top; + + public PlanarYUVLuminanceSource(byte[] yuvData, int dataWidth, int dataHeight, int left, int top, + int width, int height, boolean reverseHorizontal) { + super(width, height); + + if (left + width > dataWidth || top + height > dataHeight) { + throw new IllegalArgumentException("Crop rectangle does not fit within image data."); + } + + this.yuvData = yuvData; + this.dataWidth = dataWidth; + this.dataHeight = dataHeight; + this.left = left; + this.top = top; + if (reverseHorizontal) { + reverseHorizontal(width, height); + } + } + + @Override + public byte[] getRow(int y, byte[] row) { + if (y < 0 || y >= getHeight()) { + throw new IllegalArgumentException("Requested row is outside the image: " + y); + } + int width = getWidth(); + if (row == null || row.length < width) { + row = new byte[width]; + } + int offset = (y + top) * dataWidth + left; + System.arraycopy(yuvData, offset, row, 0, width); + return row; + } + + @Override + public byte[] getMatrix() { + int width = getWidth(); + int height = getHeight(); + + // If the caller asks for the entire underlying image, save the copy and give them the + // original data. The docs specifically warn that result.length must be ignored. + if (width == dataWidth && height == dataHeight) { + return yuvData; + } + + int area = width * height; + byte[] matrix = new byte[area]; + int inputOffset = top * dataWidth + left; + + // If the width matches the full width of the underlying data, perform a single copy. + if (width == dataWidth) { + System.arraycopy(yuvData, inputOffset, matrix, 0, area); + return matrix; + } + + // Otherwise copy one cropped row at a time. + byte[] yuv = yuvData; + for (int y = 0; y < height; y++) { + int outputOffset = y * width; + System.arraycopy(yuv, inputOffset, matrix, outputOffset, width); + inputOffset += dataWidth; + } + return matrix; + } + + @Override + public boolean isCropSupported() { + return true; + } + + public Bitmap renderCroppedGreyscaleBitmap() { + int width = getWidth(); + int height = getHeight(); + int[] pixels = new int[width * height]; + byte[] yuv = yuvData; + int inputOffset = top * dataWidth + left; + + for (int y = 0; y < height; y++) { + int outputOffset = y * width; + for (int x = 0; x < width; x++) { + int grey = yuv[inputOffset + x] & 0xff; + pixels[outputOffset + x] = 0xFF000000 | (grey * 0x00010101); + } + inputOffset += dataWidth; + } + + Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + bitmap.setPixels(pixels, 0, width, 0, 0, width, height); + return bitmap; + } + + private void reverseHorizontal(int width, int height) { + byte[] yuvData = this.yuvData; + for (int y = 0, rowStart = top * dataWidth + left; y < height; y++, rowStart += dataWidth) { + int middle = rowStart + width / 2; + for (int x1 = rowStart, x2 = rowStart + width - 1; x1 < middle; x1++, x2--) { + byte temp = yuvData[x1]; + yuvData[x1] = yuvData[x2]; + yuvData[x2] = temp; + } + } + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/PreferencesActivity.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/PreferencesActivity.java new file mode 100755 index 0000000000..3461714ac3 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/PreferencesActivity.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2008 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.evergreen_ils.barcodescan; + +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.os.Bundle; +import android.preference.CheckBoxPreference; +import android.preference.PreferenceActivity; +import android.preference.PreferenceScreen; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * The main settings activity. + * + * @author dswitkin@google.com (Daniel Switkin) + */ +public final class PreferencesActivity extends PreferenceActivity + implements OnSharedPreferenceChangeListener { + + public static final String KEY_DECODE_1D = "preferences_decode_1D"; + public static final String KEY_DECODE_QR = "preferences_decode_QR"; + public static final String KEY_DECODE_DATA_MATRIX = "preferences_decode_Data_Matrix"; + public static final String KEY_CUSTOM_PRODUCT_SEARCH = "preferences_custom_product_search"; + + public static final String KEY_REVERSE_IMAGE = "preferences_reverse_image"; + public static final String KEY_PLAY_BEEP = "preferences_play_beep"; + public static final String KEY_VIBRATE = "preferences_vibrate"; + public static final String KEY_COPY_TO_CLIPBOARD = "preferences_copy_to_clipboard"; + public static final String KEY_FRONT_LIGHT = "preferences_front_light"; + public static final String KEY_BULK_MODE = "preferences_bulk_mode"; + public static final String KEY_REMEMBER_DUPLICATES = "preferences_remember_duplicates"; + public static final String KEY_SUPPLEMENTAL = "preferences_supplemental"; + + public static final String KEY_HELP_VERSION_SHOWN = "preferences_help_version_shown"; + public static final String KEY_NOT_OUR_RESULTS_SHOWN = "preferences_not_out_results_shown"; + + private CheckBoxPreference decode1D; + private CheckBoxPreference decodeQR; + private CheckBoxPreference decodeDataMatrix; + + @Override + protected void onCreate(Bundle icicle) { + super.onCreate(icicle); + // addPreferencesFromResource(R.xml.preferences); + + PreferenceScreen preferences = getPreferenceScreen(); + preferences.getSharedPreferences().registerOnSharedPreferenceChangeListener(this); + decode1D = (CheckBoxPreference) preferences.findPreference(KEY_DECODE_1D); + decodeQR = (CheckBoxPreference) preferences.findPreference(KEY_DECODE_QR); + decodeDataMatrix = (CheckBoxPreference) preferences.findPreference(KEY_DECODE_DATA_MATRIX); + disableLastCheckedPref(); + } + + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + disableLastCheckedPref(); + } + + private void disableLastCheckedPref() { + Collection checked = new ArrayList(3); + if (decode1D.isChecked()) { + checked.add(decode1D); + } + if (decodeQR.isChecked()) { + checked.add(decodeQR); + } + if (decodeDataMatrix.isChecked()) { + checked.add(decodeDataMatrix); + } + boolean disable = checked.size() < 2; + CheckBoxPreference[] checkBoxPreferences = {decode1D, decodeQR, decodeDataMatrix}; + for (CheckBoxPreference pref : checkBoxPreferences) { + pref.setEnabled(!(disable && checked.contains(pref))); + } + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/ViewfinderResultPointCallback.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/ViewfinderResultPointCallback.java new file mode 100755 index 0000000000..7a90f6343f --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/ViewfinderResultPointCallback.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2009 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.evergreen_ils.barcodescan; + +import com.google.zxing.ResultPoint; +import com.google.zxing.ResultPointCallback; + +final class ViewfinderResultPointCallback implements ResultPointCallback { + + private final ViewfinderView viewfinderView; + + ViewfinderResultPointCallback(ViewfinderView viewfinderView) { + this.viewfinderView = viewfinderView; + } + + public void foundPossibleResultPoint(ResultPoint point) { + viewfinderView.addPossibleResultPoint(point); + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/ViewfinderView.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/ViewfinderView.java new file mode 100755 index 0000000000..44ab328523 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/ViewfinderView.java @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2008 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.evergreen_ils.barcodescan; + +import java.util.ArrayList; +import java.util.List; + +import org.evergreen_ils.R; +import org.evergreen_ils.barcodescan.camera.CameraManager; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.util.AttributeSet; +import android.view.View; + +import com.google.zxing.ResultPoint; + +/** + * This view is overlaid on top of the camera preview. It adds the viewfinder rectangle and partial + * transparency outside it, as well as the laser scanner animation and result points. + * + * @author dswitkin@google.com (Daniel Switkin) + */ +public final class ViewfinderView extends View { + + private static final int[] SCANNER_ALPHA = {0, 64, 128, 192, 255, 192, 128, 64}; + private static final long ANIMATION_DELAY = 80L; + private static final int CURRENT_POINT_OPACITY = 0xA0; + private static final int MAX_RESULT_POINTS = 20; + private static final int POINT_SIZE = 6; + + private CameraManager cameraManager; + private final Paint paint; + private Bitmap resultBitmap; + private int maskColor; + private int resultColor; + private int frameColor; + private int laserColor; + private int resultPointColor; + private int scannerAlpha; + private List possibleResultPoints; + private List lastPossibleResultPoints; + + // This constructor is used when the class is built from an XML resource. + public ViewfinderView(Context context, AttributeSet attrs) { + super(context, attrs); + + // Initialize these once for performance rather than calling them every time in onDraw(). + paint = new Paint(Paint.ANTI_ALIAS_FLAG); + Resources resources = getResources(); + maskColor = resources.getColor(R.color.viewfinder_mask); + resultColor = resources.getColor(R.color.result_view); + frameColor = resources.getColor(R.color.viewfinder_frame); + laserColor = resources.getColor(R.color.viewfinder_laser); + resultPointColor = resources.getColor(R.color.possible_result_points); + scannerAlpha = 0; + possibleResultPoints = new ArrayList(5); + lastPossibleResultPoints = null; + } + + public void setCameraManager(CameraManager cameraManager) { + this.cameraManager = cameraManager; + } + + + @Override + public void onDraw(Canvas canvas) { + Rect frame = cameraManager.getFramingRect(); + if (frame == null) { + return; + } + int width = canvas.getWidth(); + int height = canvas.getHeight(); + + // Draw the exterior (i.e. outside the framing rect) darkened + paint.setColor(resultBitmap != null ? resultColor : maskColor); + + canvas.drawRect(0, 0, width, frame.top, paint); + canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, paint); + canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1, paint); + canvas.drawRect(0, frame.bottom + 1, width, height, paint); + + if (resultBitmap != null) { + // Draw the opaque result bitmap over the scanning rectangle + paint.setAlpha(CURRENT_POINT_OPACITY); + canvas.drawBitmap(resultBitmap, null, frame, paint); + } else { + + // Draw a two pixel solid black border inside the framing rect + paint.setColor(frameColor); + canvas.drawRect(frame.left, frame.top, frame.right + 1, frame.top + 2, paint); + canvas.drawRect(frame.left, frame.top + 2, frame.left + 2, frame.bottom - 1, paint); + canvas.drawRect(frame.right - 1, frame.top, frame.right + 1, frame.bottom - 1, paint); + canvas.drawRect(frame.left, frame.bottom - 1, frame.right + 1, frame.bottom + 1, paint); + + // Draw a red "laser scanner" line through the middle to show decoding is active + paint.setColor(laserColor); + paint.setAlpha(SCANNER_ALPHA[scannerAlpha]); + scannerAlpha = (scannerAlpha + 1) % SCANNER_ALPHA.length; + int middle = frame.height() / 2 + frame.top; + canvas.drawRect(frame.left + 2, middle - 1, frame.right - 1, middle + 2, paint); + + Rect previewFrame = cameraManager.getFramingRectInPreview(); + float scaleX = frame.width() / (float) previewFrame.width(); + float scaleY = frame.height() / (float) previewFrame.height(); + + List currentPossible = possibleResultPoints; + List currentLast = lastPossibleResultPoints; + int frameLeft = frame.left; + int frameTop = frame.top; + if (currentPossible.isEmpty()) { + lastPossibleResultPoints = null; + } else { + possibleResultPoints = new ArrayList(5); + lastPossibleResultPoints = currentPossible; + paint.setAlpha(CURRENT_POINT_OPACITY); + paint.setColor(resultPointColor); + synchronized (currentPossible) { + for (ResultPoint point : currentPossible) { + canvas.drawCircle(frameLeft + (int) (point.getX() * scaleX), + frameTop + (int) (point.getY() * scaleY), + POINT_SIZE, paint); + } + } + } + if (currentLast != null) { + paint.setAlpha(CURRENT_POINT_OPACITY / 2); + paint.setColor(resultPointColor); + synchronized (currentLast) { + float radius = POINT_SIZE / 2.0f; + for (ResultPoint point : currentLast) { + canvas.drawCircle(frameLeft + (int) (point.getX() * scaleX), + frameTop + (int) (point.getY() * scaleY), + radius, paint); + } + } + } + + // Request another update at the animation interval, but only repaint the laser line, + // not the entire viewfinder mask. + postInvalidateDelayed(ANIMATION_DELAY, + frame.left - POINT_SIZE, + frame.top - POINT_SIZE, + frame.right + POINT_SIZE, + frame.bottom + POINT_SIZE); + } + } + + public void drawViewfinder() { + Bitmap resultBitmap = this.resultBitmap; + this.resultBitmap = null; + if (resultBitmap != null) { + resultBitmap.recycle(); + } + invalidate(); + } + + /** + * Draw a bitmap with the result points highlighted instead of the live scanning display. + * + * @param barcode An image of the decoded barcode. + */ + public void drawResultBitmap(Bitmap barcode) { + resultBitmap = barcode; + invalidate(); + } + + public void addPossibleResultPoint(ResultPoint point) { + List points = possibleResultPoints; + synchronized (points) { + points.add(point); + int size = points.size(); + if (size > MAX_RESULT_POINTS) { + // trim it + points.subList(0, size - MAX_RESULT_POINTS / 2).clear(); + } + } + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/camera/AutoFocusCallback.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/camera/AutoFocusCallback.java new file mode 100755 index 0000000000..c19fd2db13 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/camera/AutoFocusCallback.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2010 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.evergreen_ils.barcodescan.camera; + +import android.hardware.Camera; +import android.os.Handler; +import android.os.Message; +import android.util.Log; + +final class AutoFocusCallback implements Camera.AutoFocusCallback { + + private static final String TAG = AutoFocusCallback.class.getSimpleName(); + + private static final long AUTOFOCUS_INTERVAL_MS = 1500L; + + private Handler autoFocusHandler; + private int autoFocusMessage; + + void setHandler(Handler autoFocusHandler, int autoFocusMessage) { + this.autoFocusHandler = autoFocusHandler; + this.autoFocusMessage = autoFocusMessage; + } + + public void onAutoFocus(boolean success, Camera camera) { + if (autoFocusHandler != null) { + Message message = autoFocusHandler.obtainMessage(autoFocusMessage, success); + // Simulate continuous autofocus by sending a focus request every + // AUTOFOCUS_INTERVAL_MS milliseconds. + //Log.d(TAG, "Got auto-focus callback; requesting another"); + autoFocusHandler.sendMessageDelayed(message, AUTOFOCUS_INTERVAL_MS); + autoFocusHandler = null; + } else { + Log.d(TAG, "Got auto-focus callback, but no handler for it"); + } + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/camera/CameraConfigurationManager.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/camera/CameraConfigurationManager.java new file mode 100755 index 0000000000..2c59126522 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/camera/CameraConfigurationManager.java @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2010 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.evergreen_ils.barcodescan.camera; + +import java.util.Collection; + +import org.evergreen_ils.barcodescan.PreferencesActivity; + +import android.content.Context; +import android.content.SharedPreferences; +import android.graphics.Point; +import android.hardware.Camera; +import android.preference.PreferenceManager; +import android.util.Log; +import android.view.Display; +import android.view.WindowManager; + +/** + * A class which deals with reading, parsing, and setting the camera parameters which are used to + * configure the camera hardware. + */ +final class CameraConfigurationManager { + + private static final String TAG = "CameraConfiguration"; + private static final int MIN_PREVIEW_PIXELS = 320 * 240; // small screen + private static final int MAX_PREVIEW_PIXELS = 800 * 480; // large/HD screen + + private final Context context; + private Point screenResolution; + private Point cameraResolution; + + CameraConfigurationManager(Context context) { + this.context = context; + } + + /** + * Reads, one time, values from the camera that are needed by the app. + */ + void initFromCameraParameters(Camera camera) { + Camera.Parameters parameters = camera.getParameters(); + WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + Display display = manager.getDefaultDisplay(); + int width = display.getWidth(); + int height = display.getHeight(); + // We're landscape-only, and have apparently seen issues with display thinking it's portrait + // when waking from sleep. If it's not landscape, assume it's mistaken and reverse them: + if (width < height) { + Log.i(TAG, "Display reports portrait orientation; assuming this is incorrect"); + int temp = width; + width = height; + height = temp; + } + screenResolution = new Point(width, height); + Log.i(TAG, "Screen resolution: " + screenResolution); + cameraResolution = findBestPreviewSizeValue(parameters, screenResolution, false); + Log.i(TAG, "Camera resolution: " + cameraResolution); + } + + void setDesiredCameraParameters(Camera camera) { + Camera.Parameters parameters = camera.getParameters(); + + if (parameters == null) { + Log.w(TAG, "Device error: no camera parameters are available. Proceeding without configuration."); + return; + } + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + + initializeTorch(parameters, prefs); + String focusMode = findSettableValue(parameters.getSupportedFocusModes(), + Camera.Parameters.FOCUS_MODE_AUTO, + Camera.Parameters.FOCUS_MODE_MACRO); + if (focusMode != null) { + parameters.setFocusMode(focusMode); + } + + parameters.setPreviewSize(cameraResolution.x, cameraResolution.y); + camera.setParameters(parameters); + } + + Point getCameraResolution() { + return cameraResolution; + } + + Point getScreenResolution() { + return screenResolution; + } + + void setTorch(Camera camera, boolean newSetting) { + Camera.Parameters parameters = camera.getParameters(); + doSetTorch(parameters, newSetting); + camera.setParameters(parameters); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + boolean currentSetting = prefs.getBoolean(PreferencesActivity.KEY_FRONT_LIGHT, false); + if (currentSetting != newSetting) { + SharedPreferences.Editor editor = prefs.edit(); + editor.putBoolean(PreferencesActivity.KEY_FRONT_LIGHT, newSetting); + editor.commit(); + } + } + + private static void initializeTorch(Camera.Parameters parameters, SharedPreferences prefs) { + boolean currentSetting = prefs.getBoolean(PreferencesActivity.KEY_FRONT_LIGHT, false); + doSetTorch(parameters, currentSetting); + } + + private static void doSetTorch(Camera.Parameters parameters, boolean newSetting) { + String flashMode; + if (newSetting) { + flashMode = findSettableValue(parameters.getSupportedFlashModes(), + Camera.Parameters.FLASH_MODE_TORCH, + Camera.Parameters.FLASH_MODE_ON); + } else { + flashMode = findSettableValue(parameters.getSupportedFlashModes(), + Camera.Parameters.FLASH_MODE_OFF); + } + if (flashMode != null) { + parameters.setFlashMode(flashMode); + } + } + + private static Point findBestPreviewSizeValue(Camera.Parameters parameters, + Point screenResolution, + boolean portrait) { + Point bestSize = null; + int diff = Integer.MAX_VALUE; + for (Camera.Size supportedPreviewSize : parameters.getSupportedPreviewSizes()) { + int pixels = supportedPreviewSize.height * supportedPreviewSize.width; + if (pixels < MIN_PREVIEW_PIXELS || pixels > MAX_PREVIEW_PIXELS) { + continue; + } + int supportedWidth = portrait ? supportedPreviewSize.height : supportedPreviewSize.width; + int supportedHeight = portrait ? supportedPreviewSize.width : supportedPreviewSize.height; + int newDiff = Math.abs(screenResolution.x * supportedHeight - supportedWidth * screenResolution.y); + if (newDiff == 0) { + bestSize = new Point(supportedWidth, supportedHeight); + break; + } + if (newDiff < diff) { + bestSize = new Point(supportedWidth, supportedHeight); + diff = newDiff; + } + } + if (bestSize == null) { + Camera.Size defaultSize = parameters.getPreviewSize(); + bestSize = new Point(defaultSize.width, defaultSize.height); + } + return bestSize; + } + + private static String findSettableValue(Collection supportedValues, + String... desiredValues) { + Log.i(TAG, "Supported values: " + supportedValues); + String result = null; + if (supportedValues != null) { + for (String desiredValue : desiredValues) { + if (supportedValues.contains(desiredValue)) { + result = desiredValue; + break; + } + } + } + Log.i(TAG, "Settable value: " + result); + return result; + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/camera/CameraManager.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/camera/CameraManager.java new file mode 100755 index 0000000000..ce3d53833a --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/camera/CameraManager.java @@ -0,0 +1,280 @@ +/* + * Copyright (C) 2008 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package org.evergreen_ils.barcodescan.camera; + +import java.io.IOException; + +import org.evergreen_ils.barcodescan.PlanarYUVLuminanceSource; +import org.evergreen_ils.barcodescan.PreferencesActivity; + +import android.content.Context; +import android.content.SharedPreferences; +import android.graphics.Point; +import android.graphics.Rect; +import android.hardware.Camera; +import android.os.Handler; +import android.preference.PreferenceManager; +import android.util.Log; +import android.view.SurfaceHolder; + +/** + * This object wraps the Camera service object and expects to be the only one talking to it. The + * implementation encapsulates the steps needed to take preview-sized images, which are used for + * both preview and decoding. + * + * @author dswitkin@google.com (Daniel Switkin) + */ +public final class CameraManager { + + private static final String TAG = CameraManager.class.getSimpleName(); + + private static final int MIN_FRAME_WIDTH = 240; + private static final int MIN_FRAME_HEIGHT = 240; + private static final int MAX_FRAME_WIDTH = 600; + private static final int MAX_FRAME_HEIGHT = 400; + + private final Context context; + private final CameraConfigurationManager configManager; + private Camera camera; + private Rect framingRect; + private Rect framingRectInPreview; + private boolean initialized; + private boolean previewing; + private boolean reverseImage; + private int requestedFramingRectWidth; + private int requestedFramingRectHeight; + /** + * Preview frames are delivered here, which we pass on to the registered handler. Make sure to + * clear the handler so it will only receive one message. + */ + private final PreviewCallback previewCallback; + /** Autofocus callbacks arrive here, and are dispatched to the Handler which requested them. */ + private final AutoFocusCallback autoFocusCallback; + + public CameraManager(Context context) { + this.context = context; + this.configManager = new CameraConfigurationManager(context); + previewCallback = new PreviewCallback(configManager); + autoFocusCallback = new AutoFocusCallback(); + } + + /** + * Opens the camera driver and initializes the hardware parameters. + * + * @param holder The surface object which the camera will draw preview frames into. + * @throws IOException Indicates the camera driver failed to open. + */ + public void openDriver(SurfaceHolder holder) throws IOException { + Camera theCamera = camera; + if (theCamera == null) { + theCamera = Camera.open(); + if (theCamera == null) { + throw new IOException(); + } + camera = theCamera; + } + theCamera.setPreviewDisplay(holder); + + if (!initialized) { + initialized = true; + configManager.initFromCameraParameters(theCamera); + if (requestedFramingRectWidth > 0 && requestedFramingRectHeight > 0) { + setManualFramingRect(requestedFramingRectWidth, requestedFramingRectHeight); + requestedFramingRectWidth = 0; + requestedFramingRectHeight = 0; + } + } + configManager.setDesiredCameraParameters(theCamera); + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + reverseImage = prefs.getBoolean(PreferencesActivity.KEY_REVERSE_IMAGE, false); + } + + /** + * Closes the camera driver if still in use. + */ + public void closeDriver() { + if (camera != null) { + camera.release(); + camera = null; + // Make sure to clear these each time we close the camera, so that any scanning rect + // requested by intent is forgotten. + framingRect = null; + framingRectInPreview = null; + } + } + + /** + * Asks the camera hardware to begin drawing preview frames to the screen. + */ + public void startPreview() { + Camera theCamera = camera; + if (theCamera != null && !previewing) { + theCamera.startPreview(); + previewing = true; + } + } + + /** + * Tells the camera to stop drawing preview frames. + */ + public void stopPreview() { + if (camera != null && previewing) { + camera.stopPreview(); + previewCallback.setHandler(null, 0); + autoFocusCallback.setHandler(null, 0); + previewing = false; + } + } + + /** + * A single preview frame will be returned to the handler supplied. The data will arrive as byte[] + * in the message.obj field, with width and height encoded as message.arg1 and message.arg2, + * respectively. + * + * @param handler The handler to send the message to. + * @param message The what field of the message to be sent. + */ + public void requestPreviewFrame(Handler handler, int message) { + Camera theCamera = camera; + if (theCamera != null && previewing) { + previewCallback.setHandler(handler, message); + theCamera.setOneShotPreviewCallback(previewCallback); + } + } + + /** + * Asks the camera hardware to perform an autofocus. + * + * @param handler The Handler to notify when the autofocus completes. + * @param message The message to deliver. + */ + public void requestAutoFocus(Handler handler, int message) { + if (camera != null && previewing) { + autoFocusCallback.setHandler(handler, message); + try { + camera.autoFocus(autoFocusCallback); + } catch (RuntimeException re) { + // Have heard RuntimeException reported in Android 4.0.x+; continue? + Log.w(TAG, "Unexpected exception while focusing", re); + } + } + } + + /** + * Calculates the framing rect which the UI should draw to show the user where to place the + * barcode. This target helps with alignment as well as forces the user to hold the device + * far enough away to ensure the image will be in focus. + * + * @return The rectangle to draw on screen in window coordinates. + */ + public Rect getFramingRect() { + if (framingRect == null) { + if (camera == null) { + return null; + } + Point screenResolution = configManager.getScreenResolution(); + int width = screenResolution.x * 3 / 4; + if (width < MIN_FRAME_WIDTH) { + width = MIN_FRAME_WIDTH; + } else if (width > MAX_FRAME_WIDTH) { + width = MAX_FRAME_WIDTH; + } + int height = screenResolution.y * 3 / 4; + if (height < MIN_FRAME_HEIGHT) { + height = MIN_FRAME_HEIGHT; + } else if (height > MAX_FRAME_HEIGHT) { + height = MAX_FRAME_HEIGHT; + } + int leftOffset = (screenResolution.x - width) / 2; + int topOffset = (screenResolution.y - height) / 2; + framingRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height); + Log.d(TAG, "Calculated framing rect: " + framingRect); + } + return framingRect; + } + + /** + * Like {@link #getFramingRect} but coordinates are in terms of the preview frame, + * not UI / screen. + */ + public Rect getFramingRectInPreview() { + if (framingRectInPreview == null) { + Rect framingRect = getFramingRect(); + if (framingRect == null) { + return null; + } + Rect rect = new Rect(framingRect); + Point cameraResolution = configManager.getCameraResolution(); + Point screenResolution = configManager.getScreenResolution(); + rect.left = rect.left * cameraResolution.x / screenResolution.x; + rect.right = rect.right * cameraResolution.x / screenResolution.x; + rect.top = rect.top * cameraResolution.y / screenResolution.y; + rect.bottom = rect.bottom * cameraResolution.y / screenResolution.y; + framingRectInPreview = rect; + } + return framingRectInPreview; + } + + /** + * Allows third party apps to specify the scanning rectangle dimensions, rather than determine + * them automatically based on screen resolution. + * + * @param width The width in pixels to scan. + * @param height The height in pixels to scan. + */ + public void setManualFramingRect(int width, int height) { + if (initialized) { + Point screenResolution = configManager.getScreenResolution(); + if (width > screenResolution.x) { + width = screenResolution.x; + } + if (height > screenResolution.y) { + height = screenResolution.y; + } + int leftOffset = (screenResolution.x - width) / 2; + int topOffset = (screenResolution.y - height) / 2; + framingRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height); + Log.d(TAG, "Calculated manual framing rect: " + framingRect); + framingRectInPreview = null; + } else { + requestedFramingRectWidth = width; + requestedFramingRectHeight = height; + } + } + + /** + * A factory method to build the appropriate LuminanceSource object based on the format + * of the preview buffers, as described by Camera.Parameters. + * + * @param data A preview frame. + * @param width The width of the image. + * @param height The height of the image. + * @return A PlanarYUVLuminanceSource instance. + */ + public PlanarYUVLuminanceSource buildLuminanceSource(byte[] data, int width, int height) { + Rect rect = getFramingRectInPreview(); + if (rect == null) { + return null; + } + // Go ahead and assume it's YUV rather than die. + return new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top, + rect.width(), rect.height(), reverseImage); + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/camera/FlashlightManager.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/camera/FlashlightManager.java new file mode 100755 index 0000000000..25b990605c --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/camera/FlashlightManager.java @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2010 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.evergreen_ils.barcodescan.camera; + +import android.os.IBinder; +import android.util.Log; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * This class is used to activate the weak light on some camera phones (not flash) + * in order to illuminate surfaces for scanning. There is no official way to do this, + * but, classes which allow access to this function still exist on some devices. + * This therefore proceeds through a great deal of reflection. + * + * See http://almondmendoza.com/2009/01/05/changing-the-screen-brightness-programatically/ and + * http://code.google.com/p/droidled/source/browse/trunk/src/com/droidled/demo/DroidLED.java . + * Thanks to Ryan Alford for pointing out the availability of this class. + */ +final class FlashlightManager { + + private static final String TAG = FlashlightManager.class.getSimpleName(); + + private static final Object iHardwareService; + private static final Method setFlashEnabledMethod; + static { + iHardwareService = getHardwareService(); + setFlashEnabledMethod = getSetFlashEnabledMethod(iHardwareService); + if (iHardwareService == null) { + Log.v(TAG, "This device does supports control of a flashlight"); + } else { + Log.v(TAG, "This device does not support control of a flashlight"); + } + } + + private FlashlightManager() { + } + + private static Object getHardwareService() { + Class serviceManagerClass = maybeForName("android.os.ServiceManager"); + if (serviceManagerClass == null) { + return null; + } + + Method getServiceMethod = maybeGetMethod(serviceManagerClass, "getService", String.class); + if (getServiceMethod == null) { + return null; + } + + Object hardwareService = invoke(getServiceMethod, null, "hardware"); + if (hardwareService == null) { + return null; + } + + Class iHardwareServiceStubClass = maybeForName("android.os.IHardwareService$Stub"); + if (iHardwareServiceStubClass == null) { + return null; + } + + Method asInterfaceMethod = maybeGetMethod(iHardwareServiceStubClass, "asInterface", + IBinder.class); + if (asInterfaceMethod == null) { + return null; + } + + return invoke(asInterfaceMethod, null, hardwareService); + } + + private static Method getSetFlashEnabledMethod(Object iHardwareService) { + if (iHardwareService == null) { + return null; + } + Class proxyClass = iHardwareService.getClass(); + return maybeGetMethod(proxyClass, "setFlashlightEnabled", boolean.class); + } + + private static Class maybeForName(String name) { + try { + return Class.forName(name); + } catch (ClassNotFoundException cnfe) { + // OK + return null; + } catch (RuntimeException re) { + Log.w(TAG, "Unexpected error while finding class " + name, re); + return null; + } + } + + private static Method maybeGetMethod(Class clazz, String name, Class... argClasses) { + try { + return clazz.getMethod(name, argClasses); + } catch (NoSuchMethodException nsme) { + // OK + return null; + } catch (RuntimeException re) { + Log.w(TAG, "Unexpected error while finding method " + name, re); + return null; + } + } + + private static Object invoke(Method method, Object instance, Object... args) { + try { + return method.invoke(instance, args); + } catch (IllegalAccessException e) { + Log.w(TAG, "Unexpected error while invoking " + method, e); + return null; + } catch (InvocationTargetException e) { + Log.w(TAG, "Unexpected error while invoking " + method, e.getCause()); + return null; + } catch (RuntimeException re) { + Log.w(TAG, "Unexpected error while invoking " + method, re); + return null; + } + } + + static void enableFlashlight() { + setFlashlight(true); + } + + static void disableFlashlight() { + setFlashlight(false); + } + + private static void setFlashlight(boolean active) { + if (iHardwareService != null) { + invoke(setFlashEnabledMethod, iHardwareService, active); + } + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/camera/PreviewCallback.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/camera/PreviewCallback.java new file mode 100755 index 0000000000..807227d272 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/camera/PreviewCallback.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2010 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.evergreen_ils.barcodescan.camera; +/* + * Copyright (C) 2010 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import android.graphics.Point; +import android.hardware.Camera; +import android.os.Handler; +import android.os.Message; +import android.util.Log; + +final class PreviewCallback implements Camera.PreviewCallback { + + private static final String TAG = PreviewCallback.class.getSimpleName(); + + private final CameraConfigurationManager configManager; + private Handler previewHandler; + private int previewMessage; + + PreviewCallback(CameraConfigurationManager configManager) { + this.configManager = configManager; + } + + void setHandler(Handler previewHandler, int previewMessage) { + this.previewHandler = previewHandler; + this.previewMessage = previewMessage; + } + + @Override + public void onPreviewFrame(byte[] data, Camera camera) { + Point cameraResolution = configManager.getCameraResolution(); + Handler thePreviewHandler = previewHandler; + if (thePreviewHandler != null) { + Message message = thePreviewHandler.obtainMessage(previewMessage, cameraResolution.x, + cameraResolution.y, data); + message.sendToTarget(); + previewHandler = null; + } else { + Log.d(TAG, "Got preview callback, but no handler for it"); + } + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/result/ResultHandler.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/result/ResultHandler.java new file mode 100755 index 0000000000..8e1939866d --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/barcodescan/result/ResultHandler.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2008 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.evergreen_ils.barcodescan.result; + +import com.google.zxing.Result; +import com.google.zxing.client.result.ParsedResult; +import com.google.zxing.client.result.ResultParser; + +import android.app.Activity; + +/** + * A base class for the Android-specific barcode handlers. These allow the app to polymorphically + * suggest the appropriate actions for each data type. + * + * This class also contains a bunch of utility methods to take common actions like opening a URL. + * They could easily be moved into a helper object, but it can't be static because the Activity + * instance is needed to launch an intent. + * + * @author dswitkin@google.com (Daniel Switkin) + */ +public class ResultHandler { + + private final ParsedResult result; + private final Activity activity; + private final Result rawResult; + + public ResultHandler(Activity activity, Result rawResult) { + this.activity = activity; + this.rawResult = rawResult; + result = parseResult(rawResult); + } + + + public ParsedResult getResult() { + return result; + } + + private static ParsedResult parseResult(Result rawResult) { + return ResultParser.parseResult(rawResult); + } + + /** + * Create a possibly styled string for the contents of the current barcode. + * + * @return The text to be displayed. + */ + public CharSequence getDisplayContents() { + String contents = result.getDisplayResult(); + return contents.replace("\r", ""); + } +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/database/DatabaseManager.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/database/DatabaseManager.java new file mode 100644 index 0000000000..860975e883 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/database/DatabaseManager.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.database; + +import java.util.HashMap; +import java.util.logging.Logger; + +import org.androwrapee.db.DefaultDAO; +import org.androwrapee.db.DefaultDatabaseHelper; +import org.androwrapee.db.IllegalClassStructureException; +import org.androwrapee.db.ReflectionManager; +import org.evergreen_ils.services.NotificationAlert; + +import android.content.Context; +import android.util.Log; + +/** + * The Class DatabaseDefaults. + */ +public class DatabaseManager { + + public static String TAG = "DatabaseManager"; + + /** The DATABASE NAME. */ + public static final String DATABASE_NAME = "evergreen.db"; + + /** The DATABASE VERSION. */ + public static final int DATABASE_VERSION = 1; + + /** The db helper. */ + private static DefaultDatabaseHelper dbHelper = null; + + /** The singleton reflection managers map. */ + @SuppressWarnings("rawtypes") + private static HashMap rmMap = new HashMap(); + + @SuppressWarnings("rawtypes") + private static HashMap daoMap = new HashMap(); + + /** + * Gets the Singleton database helper. + * + * @return the dB helper + */ + public static DefaultDatabaseHelper getDBHelper(Context context) { + if (dbHelper == null) + dbHelper = new DefaultDatabaseHelper(context, DATABASE_NAME, + DATABASE_VERSION, new Class[] { NotificationAlert.class }, + new String[] { NotificationAlert.tableName }); + return dbHelper; + } + + /** + * Gets a singleton instance of a reflection manager corresponding to a + * class. + * + * @param cls + * the class + * @return the reflection manager instance + */ + public static ReflectionManager getReflectionManagerInstance( + Class cls) { + if (rmMap.containsKey(cls)) + return rmMap.get(cls); + try { + ReflectionManager rm = new ReflectionManager(cls); + rmMap.put(cls, rm); + return rm; + } catch (IllegalClassStructureException ex) { + ex.printStackTrace(); + Log.d(TAG, + "Illegal Class Structure for class " + cls + ": " + + ex.getMessage()); + return null; + } + } + + /** + * Gets a singleton instance of a DefaultDAO object corresponding to a + * class. + * + * @param + * the generic type + * @param cls + * the class + * @param tableName + * the table name + * @return the DAO instance + */ + @SuppressWarnings("unchecked") + public static synchronized DefaultDAO getDAOInstance( + Context context, Class cls, String tableName) { + if (daoMap.containsKey(cls)) + return daoMap.get(cls); + DefaultDAO dao = new DefaultDAO(cls, + DatabaseManager.getDBHelper(context), + DatabaseManager.getReflectionManagerInstance(cls), tableName); + daoMap.put(cls, dao); + return dao; + } +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/globals/EvergreenConstants.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/globals/EvergreenConstants.java new file mode 100644 index 0000000000..406c8d3ed6 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/globals/EvergreenConstants.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2013 Evergreen Open-ILS + * @author kenstir + */ +package org.evergreen_ils.globals; + +/** + * Conversion of constants from Const.pm + */ +class EvergreenConstants { + + // Copy Statuses + public static final int COPY_STATUS_AVAILABLE = 0; + public static final int COPY_STATUS_CHECKED_OUT = 1; + public static final int COPY_STATUS_BINDERY = 2; + public static final int COPY_STATUS_LOST = 3; + public static final int COPY_STATUS_MISSING = 4; + public static final int COPY_STATUS_IN_PROCESS = 5; + public static final int COPY_STATUS_IN_TRANSIT = 6; + public static final int COPY_STATUS_RESHELVING = 7; + public static final int COPY_STATUS_ON_HOLDS_SHELF= 8; + public static final int COPY_STATUS_ON_ORDER = 9; + public static final int COPY_STATUS_ILL = 10; + public static final int COPY_STATUS_CATALOGING = 11; + public static final int COPY_STATUS_RESERVES = 12; + public static final int COPY_STATUS_DISCARD = 13; + public static final int COPY_STATUS_DAMAGED = 14; + public static final int COPY_STATUS_ON_RESV_SHELF = 15; + + // Circ defaults for pre-cataloged copies + public static final int PRECAT_COPY_FINE_LEVEL = 2; + public static final int PRECAT_COPY_LOAN_DURATION = 2; + public static final int PRECAT_CALL_NUMBER = -1; + public static final int PRECAT_RECORD = -1; + + // Circ constants + public static final int CIRC_DURATION_SHORT = 1; + public static final int CIRC_DURATION_NORMAL = 2; + public static final int CIRC_DURATION_EXTENDED = 3; + public static final int REC_FINE_LEVEL_LOW = 1; + public static final int REC_FINE_LEVEL_NORMAL = 2; + public static final int REC_FINE_LEVEL_HIGH = 3; + public static final String STOP_FINES_CHECKIN = "CHECKIN"; + public static final String STOP_FINES_RENEW = "RENEW"; + public static final String STOP_FINES_LOST = "LOST"; + public static final String STOP_FINES_CLAIMSRETURNED = "CLAIMSRETURNED"; + public static final String STOP_FINES_LONGOVERDUE = "LONGOVERDUE"; + public static final String STOP_FINES_MAX_FINES = "MAXFINES"; + public static final String STOP_FINES_CLAIMS_NEVERCHECKEDOUT = "CLAIMSNEVERCHECKEDOUT"; + public static final String UNLIMITED_CIRC_DURATION = "unlimited"; + + // Settings + public static final String SETTING_LOST_PROCESSING_FEE = "circ.lost_materials_processing_fee"; + public static final String SETTING_DEF_ITEM_PRICE = "cat.default_item_price"; + public static final String SETTING_ORG_BOUNCED_EMAIL = "org.bounced_emails"; + public static final String SETTING_CHARGE_LOST_ON_ZERO = "circ.charge_lost_on_zero"; + public static final String SETTING_VOID_OVERDUE_ON_LOST = "circ.void_overdue_on_lost"; + public static final String SETTING_HOLD_SOFT_STALL = "circ.hold_stalling.soft"; + public static final String SETTING_HOLD_HARD_STALL = "circ.hold_stalling.hard"; + public static final String SETTING_HOLD_SOFT_BOUNDARY = "circ.hold_boundary.soft"; + public static final String SETTING_HOLD_HARD_BOUNDARY = "circ.hold_boundary.hard"; + public static final String SETTING_HOLD_EXPIRE = "circ.hold_expire_interval"; + public static final String SETTING_HOLD_ESIMATE_WAIT_INTERVAL = "circ.holds.default_estimated_wait_interval"; + public static final String SETTING_VOID_LOST_ON_CHECKIN = "circ.void_lost_on_checkin"; + public static final String SETTING_MAX_ACCEPT_RETURN_OF_LOST = "circ.max_accept_return_of_lost"; + public static final String SETTING_VOID_LOST_PROCESS_FEE_ON_CHECKIN = "circ.void_lost_proc_fee_on_checkin"; + public static final String SETTING_RESTORE_OVERDUE_ON_LOST_RETURN = "circ.restore_overdue_on_lost_return"; + public static final String SETTING_LOST_IMMEDIATELY_AVAILABLE = "circ.lost_immediately_available"; + public static final String SETTING_BLOCK_HOLD_FOR_EXPIRED_PATRON = "circ.holds.expired_patron_block"; + public static final String SETTING_GENERATE_OVERDUE_ON_LOST_RETURN = "circ.lost.generate_overdue_on_checkin"; + + public static final String HOLD_TYPE_COPY = "C"; + public static final String HOLD_TYPE_FORCE = "F"; + public static final String HOLD_TYPE_RECALL = "R"; + public static final String HOLD_TYPE_ISSUANCE = "I"; + public static final String HOLD_TYPE_VOLUME = "V"; + public static final String HOLD_TYPE_TITLE = "T"; + public static final String HOLD_TYPE_METARECORD = "M"; + public static final String HOLD_TYPE_MONOPART = "P"; + + public static final String BILLING_TYPE_OVERDUE_MATERIALS = "Overdue materials"; + public static final String BILLING_TYPE_COLLECTION_FEE = "Long Overdue Collection Fee"; + public static final String BILLING_TYPE_DEPOSIT = "System: Deposit"; + public static final String BILLING_TYPE_RENTAL = "System: Rental"; + public static final String BILLING_NOTE_SYSTEM = "SYSTEM GENERATED"; + + public static final String ACQ_DEBIT_TYPE_PURCHASE = "purchase"; + public static final String ACQ_DEBIT_TYPE_TRANSFER = "xfer"; + + // all penalties with ID < 100 are managed automatically + public static final int PENALTY_AUTO_ID = 100; + public static final int PENALTY_PATRON_EXCEEDS_FINES = 1; + public static final int PENALTY_PATRON_EXCEEDS_OVERDUE_COUNT = 2; + public static final int PENALTY_INVALID_PATRON_ADDRESS = 29; + + public static final int BILLING_TYPE_NOTIFICATION_FEE = 9; +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/globals/GlobalConfigs.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/globals/GlobalConfigs.java new file mode 100644 index 0000000000..3d02947216 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/globals/GlobalConfigs.java @@ -0,0 +1,283 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.globals; + +import android.content.Context; +import android.net.ConnectivityManager; +import android.util.Log; +import org.evergreen_ils.accountAccess.AccountAccess; +import org.evergreen_ils.accountAccess.SessionNotFoundException; +import org.evergreen_ils.searchCatalog.Organisation; +import org.evergreen_ils.searchCatalog.SearchCatalog; +import org.open_ils.idl.IDLParser; +import org.opensrf.util.JSONException; +import org.opensrf.util.JSONReader; + +import java.io.InputStream; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; + +public class GlobalConfigs { + + public static String IDL_FILE_FROM_ROOT = "/reports/fm_IDL.xml"; + public static String IDL_FILE_FROM_ASSETS = "fm_IDL.xml"; + public static String httpAddress = ""; + + private boolean init = false; + + private static String TAG = "GlobalConfigs"; + + private static boolean debugMode = true;//KCXXX make a developer preference + + public static boolean loadedIDL = false; + + public static boolean loadedOrgTree = false; + + public static String hold_icon_address = "/opac/images/tor/"; + + // two days notification before checkout expires, this can be modified from + // preferences + public static int NOTIFICATION_BEFORE_CHECKOUT_EXPIRATION = 2; + + // to parse date from requests + public static final String datePattern = "yyyy-MM-dd'T'hh:mm:ssZ"; + + /** The locale. */ + public String locale = "en-US"; + + private static GlobalConfigs globalConfigSingleton = null; + /** The organisations. */ + public ArrayList organisations; + + /** The collections request. */ + private String collectionsRequest = "/opac/common/js/" + locale + + "/OrgTree.js"; + + private GlobalConfigs(Context context) { + + initialize(context); + } + + public static GlobalConfigs getGlobalConfigs(Context context) { + + if (globalConfigSingleton == null) { + globalConfigSingleton = new GlobalConfigs(context); + } + + return globalConfigSingleton; + } + + /* + * Initialize function that retrieves IDL file and Orgs file + */ + private boolean initialize(Context context) { + if (!init) { + loadIDLFile(context); + getOrganisations(); + getCopyStatusesAvailable((ConnectivityManager) context + .getSystemService(Context.CONNECTIVITY_SERVICE)); + init = true; + return true; + } + return false; + } + + public static boolean isDebugMode() { + return debugMode; + } + + public static void setDebugMode(boolean debugMode) { + GlobalConfigs.debugMode = debugMode; + } + + public void loadIDLFile(Context context) { + + try { + Log.d(TAG, "loadIDLFile start"); + //@TODO maybe switch back to IDL_FILE_FROM_ROOT?class=circ&class=au&class=mvr&class=acp + InputStream in_IDL = context.getAssets().open(IDL_FILE_FROM_ASSETS); + IDLParser parser = new IDLParser(in_IDL); + parser.setKeepIDLObjects(false); + Log.d(TAG, "loadIDLFile parse"); + long start_ms = System.currentTimeMillis(); + parser.parse(); + long duration_ms = System.currentTimeMillis() - start_ms; + Log.d(TAG, "loadIDLFile parse took "+duration_ms+"ms"); + } catch (Exception e) { + Log.w(TAG, "Error in parsing IDL file", e); + } + + loadedIDL = true; + } + + /** + * Fetch the OrgTree.js file, and from it parse the list of organisations. + */ + public void getOrganisations() { + + String orgFile = null; + + organisations = new ArrayList(); + + try { + Log.d(TAG, "getOrg fetching "+httpAddress + collectionsRequest); + orgFile = Utils.getNetPageContent(httpAddress + collectionsRequest); + } catch (Exception e) { + } + + if (orgFile != null) { + long start_ms = System.currentTimeMillis(); + Log.d(TAG, "getOrg loading"); + organisations = new ArrayList(); + + // in case of wrong file + if (orgFile.indexOf("=") == -1) + return; + String orgArray = orgFile.substring(orgFile.indexOf("=") + 1, + orgFile.indexOf(";")); + Log.d(TAG, "getOrg array=" + orgArray.substring(0, orgArray.length()>50 ? 50 : -1)); + + // Parse javascript list + // Format: [[id, ou_type, parent_ou, name, opac_visible, shortname],...] + // Sample: [[149,3,146,"Agawam",0,"AGAWAM_MA"], + // [150,4,149,"Agawam Public Library",1,"AGAWAM"],...] + // ou_type can be treated as hierarchical nesting level + List orgList; + try { + orgList = new JSONReader(orgArray).readArray(); + } catch (JSONException e) { + Log.d(TAG, "getOrg failed parsing array", e); + return; + } + + // Convert json list into array of Organisation + for (int i=0; i() { + @Override + public int compare(Organisation a, Organisation b) { + if (a.parent == null) + return -1; // root is always first + return a.name.compareTo(b.name); + } + }); + /* + for (int i=0; i 0); + } + + public static void bookCoverImage(ImageView picture, String imageID, + int size) { + + String urlS = (GlobalConfigs.httpAddress + + "/opac/extras/ac/jacket/small/" + imageID); + + Bitmap bmp = null; // create a new Bitmap variable called bmp, and + // initialize it to null + + try { + + URL url = new URL(urlS); // create a URL object from the urlS string + // above + URLConnection conn = url.openConnection(); // save conn as a + // URLConnection + + conn.connect(); // connect to the URLConnection conn + InputStream is = conn.getInputStream(); // get the image from the + // URLConnection conn using + // InputStream is + BufferedInputStream bis = new BufferedInputStream(is, 8*1024); // create a + // BufferedInputStream + // called bis + // from is + bmp = BitmapFactory.decodeStream(bis); // use bis to convert the + // stream to a bitmap image, + // and save it to bmp + int bmpHeight = bmp.getHeight(); // stores the original height of + // the image + if (bmpHeight != 1) { + double scale = size / (double) bmpHeight; // sets the scaling + // number to match the + // desired size + double bmpWidthh = (double) bmp.getWidth() * scale; // scales + // and + // stores + // the + // original + // width + // into the + // desired + // one + int bmpWidth = (int) bmpWidthh; // gets the width of the picture + // and saves it + bmp = Bitmap.createScaledBitmap(bmp, bmpWidth, size, true); // creates + // and + // stores + // a + // new + // bmp + // with + // desired + // dimensions + } + + } catch (MalformedURLException e) { // catch errors + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (IllegalStateException e) { + e.printStackTrace(); + } + picture.setImageBitmap(bmp); // send the Bitmap image bmp to pic, and + // call the method to set the image. + + } + + public static String getResponseTextcode(Object response) { + String textcode = null; + try { + textcode = ((Map) response).get("textcode"); + } catch (Exception e) { + } + return textcode; + } + + public static Object doRequest(HttpConnection conn, String service, + String methodName, String authToken, + Object[] params) throws SessionNotFoundException { + + Method method = new Method(methodName); + + Log.d(TAG, "doRequest Method :" + methodName + ": token :"+authToken+":"); + for (int i = 0; i < params.length; i++) { + method.addParam(params[i]); + Log.d(TAG, "Param " + i + ":" + params[i]); + } + + // sync request + HttpRequest req = new GatewayRequest(conn, service, method).send(); + Object resp = null; + + try { + resp = req.recv(); + } catch (NullPointerException e) { + // I know it's bad form to catch NPE. But until I implement some kind of on-demand IDL parsing, + // this is what happens when the JSONReader tries to parse a response of an unregistered class. + // Crash if debugMode, fail if not. + Log.d(TAG, "NPE...unregistered type?", e); + if (GlobalConfigs.isDebugMode()) { + throw(e); + } + } + if (resp != null) { + Log.d(TAG, "Sync Response: " + resp); + Object response = (Object) resp; + + String textcode = getResponseTextcode(resp); + if (TextUtils.equals(textcode, "NO_SESSION")) { + Log.d(TAG, textcode); + throw new SessionNotFoundException(); + } + + return response; + } + return null; + + } + + // does not require authToken + public static Object doRequest(HttpConnection conn, String service, + String methodName, ConnectivityManager cm, Object[] params) { + + Method method = new Method(methodName); + + Log.d(TAG, "doRequest Method :" + methodName + ":"); + for (int i = 0; i < params.length; i++) { + method.addParam(params[i]); + Log.d(TAG, "Param " + i + ": " + params[i]); + } + + // sync request + HttpRequest req = new GatewayRequest(conn, service, method).send(); + Object resp; + + while ((resp = req.recv()) != null) { + Log.d(TAG, "Sync Response: " + resp); + Object response = (Object) resp; + + return response; + + } + return null; + + } + + // does not throw exception + // is fast than with checks for multiple method invocations like in search + public static Object doRequestSimple(HttpConnection conn, String service, + String methodName, Object[] params) { + + if (Looper.myLooper() == Looper.getMainLooper()) { + // running on UI thread! + throw new NullPointerException(); + } + + Method method = new Method(methodName); + Log.d(TAG, "doRequestSimple Method :" + methodName); + for (int i = 0; i < params.length; i++) { + method.addParam(params[i]); + Log.d(TAG, "Param " + i + ":" + params[i]); + } + + // sync request + HttpRequest req = new GatewayRequest(conn, service, method).send(); + Object resp; + + while ((resp = req.recv()) != null) { + Log.d(TAG, "Sync Response: " + resp); + Object response = (Object) resp; + + return response; + + } + return null; + } + + public static ShowSessionNotAvailableRunnable showSessionNotAvailableDialog( + Context context) { + + return new ShowSessionNotAvailableRunnable(context); + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/AdvancedSearchActivity.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/AdvancedSearchActivity.java new file mode 100644 index 0000000000..1065ab66c7 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/AdvancedSearchActivity.java @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.searchCatalog; + +import java.util.StringTokenizer; + +import org.evergreen_ils.R; +import org.evergreen_ils.accountAccess.AccountAccess; +import org.evergreen_ils.views.AccountScreenDashboard; +import org.evergreen_ils.views.splashscreen.SplashActivity; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup.LayoutParams; +import android.widget.Button; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.Spinner; +import android.widget.TextView; + +public class AdvancedSearchActivity extends Activity { + + private final String TAG = AdvancedSearchActivity.class.getName(); + + private AccountAccess accountAccess = null; + + private Context context; + + private Button homeButton; + + private Button myAccountButton; + + private TextView headerTitle; + + private StringBuilder advancedSearchFormattedText; + + public static final int RESULT_ADVANCED_SEARCH = 10; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (!SplashActivity.isAppInitialized()) { + SplashActivity.restartApp(this); + return; + } + + setContentView(R.layout.advanced_search); + + advancedSearchFormattedText = new StringBuilder(); + + // header portion actions + myAccountButton = (Button) findViewById(R.id.my_account_button); + myAccountButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getApplicationContext(), + AccountScreenDashboard.class); + startActivity(intent); + } + }); + + homeButton = (Button) findViewById(R.id.action_bar_home_button); + homeButton.setText(R.string.advanced_search); + homeButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getApplicationContext(), + SearchCatalogListView.class); + startActivity(intent); + } + }); + // end header portion actions + + context = this; + + final LinearLayout layout = (LinearLayout) findViewById(R.id.advanced_search_filters); + + Button addFilter = (Button) findViewById(R.id.advanced_search_add_filter_button); + + final Spinner search_index = (Spinner) findViewById(R.id.advanced_spinner_index); + final Spinner search_option = (Spinner) findViewById(R.id.advanced_spinner_option); + final EditText search_filter_text = (EditText) findViewById(R.id.advanced_search_text); + + addFilter.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + + int searchOptionVal = search_option.getSelectedItemPosition(); + + String searchText = search_index.getSelectedItem().toString() + .toLowerCase() + + ": "; + + advancedSearchFormattedText.append(search_index + .getSelectedItem().toString().toLowerCase() + + ": "); + + switch (searchOptionVal) { + + case 0: { + // contains + advancedSearchFormattedText.append(search_filter_text + .getText().toString()); + searchText = searchText + + search_filter_text.getText().toString(); + } + break; + case 1: { + // excludes + + StringTokenizer str = new StringTokenizer( + search_filter_text.getText().toString()); + + while (str.hasMoreTokens()) { + String token = str.nextToken(" "); + advancedSearchFormattedText.append(" -" + token); + searchText = searchText + " -" + token; + } + + } + break; + case 2: { + // matches exactly + advancedSearchFormattedText.append(" \"" + + search_filter_text.getText().toString() + "\""); + searchText = searchText + " \"" + + search_filter_text.getText().toString() + "\""; + } + break; + + } + + TextView text = new TextView(context); + text.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, + LayoutParams.WRAP_CONTENT)); + text.setText(searchText); + layout.addView(text); + + } + }); + + Button cancel = (Button) findViewById(R.id.advanced_search_cancel); + + cancel.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + + Button search = (Button) findViewById(R.id.advanced_search_button); + + search.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + Intent returnIntent = new Intent(); + returnIntent.putExtra("advancedSearchText", + advancedSearchFormattedText.toString()); + setResult(RESULT_ADVANCED_SEARCH, returnIntent); + finish(); + } + }); + + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/CopyCountInformation.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/CopyCountInformation.java new file mode 100644 index 0000000000..87ae779958 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/CopyCountInformation.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.searchCatalog; + +import android.util.Log; + +import java.io.Serializable; +import java.util.Map; + +public class CopyCountInformation implements Serializable { + + private final String TAG = CopyCountInformation.class.getName(); + private static final long serialVersionUID = 12343248767867L; + public Integer org_id; + public Integer count; + public Integer available; + public Integer depth; + public Integer unshadow; + + public CopyCountInformation(Object map) { + + this.org_id = ((Map) map).get("org_unit"); + this.count = ((Map) map).get("count"); + this.available = ((Map) map).get("available"); + this.depth = ((Map) map).get("depth"); + this.unshadow = ((Map) map).get("unshadow"); + + Log.d(TAG, org_id + " " + available + " " + count); + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/CopyInformation.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/CopyInformation.java new file mode 100644 index 0000000000..f548ff2c8a --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/CopyInformation.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.searchCatalog; + +import android.util.Log; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; + +public class CopyInformation implements Serializable { + + private static final long serialVersionUID = -7269334218707079463L; + + private final String TAG = CopyInformation.class.getName(); + + public Integer org_id = -1; + + public String call_number_sufix; + + public String copy_location; + + public HashMap statuses; + + // the hash from the request method + private HashMap hashValCopy; + + // global, it is initialized when orgTree and fm_ild is downloaded + + public static LinkedHashMap availableOrgStatuses; + + public LinkedHashMap statusInformation = null; + + public CopyInformation(List list) { + + org_id = Integer.parseInt((String) list.get(0)); + call_number_sufix = (String) list.get(2); + copy_location = (String) list.get(4); + + hashValCopy = (HashMap) list.get(5); + + statusInformation = new LinkedHashMap(); + + Set> set = availableOrgStatuses.entrySet(); + + Iterator> it = set.iterator(); + + while (it.hasNext()) { + Entry entry = it.next(); + + if (hashValCopy.containsKey(entry.getKey())) { + statusInformation.put(entry.getValue(), + hashValCopy.get(entry.getKey()) + ""); + Log.d(TAG, "Added " + entry.getKey() + " " + + entry.getValue() + " " + + hashValCopy.get(entry.getKey())); + } + } + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/ImageDownloader.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/ImageDownloader.java new file mode 100644 index 0000000000..85437167cc --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/ImageDownloader.java @@ -0,0 +1,481 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.evergreen_ils.searchCatalog; + +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.ref.SoftReference; +import java.lang.ref.WeakReference; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.DefaultHttpClient; +import org.evergreen_ils.R; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.net.http.AndroidHttpClient; +import android.os.AsyncTask; +import android.os.Handler; +import android.util.Log; +import android.widget.ImageView; + +/** + * This helper class download images from the Internet and binds those with the + * provided ImageView. + * + *

+ * It requires the INTERNET permission, which should be added to your + * application's manifest file. + *

+ * + * A local cache of downloaded images is maintained internally to improve + * performance. + */ +public class ImageDownloader { + private static final String LOG_TAG = "ImageDownloader"; + + public enum Mode { + NO_ASYNC_TASK, NO_DOWNLOADED_DRAWABLE, CORRECT + } + + private Mode mode = Mode.CORRECT; + + private int MIN_IMG_HEIGHT = 75; + + private int MIN_IMG_WIDTH = 30; + + private int bitmap_width; + private int bitmap_height; + private boolean scale; + + public ImageDownloader(int min_img_height) { + + MIN_IMG_HEIGHT = min_img_height; + } + + public ImageDownloader() { + + } + + public ImageDownloader(int w, int h, boolean scale) { + this.bitmap_height = h; + this.bitmap_width = w; + this.scale = scale; + MIN_IMG_HEIGHT = h; + } + + /** + * Download the specified image from the Internet and binds it to the + * provided ImageView. The binding is immediate if the image is found in the + * cache and will be done asynchronously otherwise. A null bitmap will be + * associated to the ImageView if an error occurs. + * + * @param url + * The URL of the image to download. + * @param imageView + * The ImageView to bind the downloaded image to. + */ + public void download(String url, ImageView imageView) { + resetPurgeTimer(); + Bitmap bitmap = getBitmapFromCache(url); + + if (bitmap == null) { + forceDownload(url, imageView); + } else { + cancelPotentialDownload(url, imageView); + imageView.setImageBitmap(bitmap); + } + } + + /* + * Same as download but the image is always downloaded and the cache is not + * used. Kept private at the moment as its interest is not clear. private + * void forceDownload(String url, ImageView view) { forceDownload(url, view, + * null); } + */ + + /** + * Same as download but the image is always downloaded and the cache is not + * used. Kept private at the moment as its interest is not clear. + */ + private void forceDownload(String url, ImageView imageView) { + // State sanity: url is guaranteed to never be null in + // DownloadedDrawable and cache keys. + if (url == null) { + imageView.setImageDrawable(null); + return; + } + + if (cancelPotentialDownload(url, imageView)) { + switch (mode) { + case NO_ASYNC_TASK: + Bitmap bitmap = downloadBitmap(url); + addBitmapToCache(url, bitmap); + imageView.setImageBitmap(bitmap); + break; + + case NO_DOWNLOADED_DRAWABLE: + imageView.setMinimumHeight(MIN_IMG_HEIGHT); + BitmapDownloaderTask task = new BitmapDownloaderTask(imageView); + task.execute(url); + break; + + case CORRECT: + task = new BitmapDownloaderTask(imageView); + DownloadedDrawable downloadedDrawable = new DownloadedDrawable( + task); + imageView.setImageDrawable(downloadedDrawable); + imageView.setMinimumHeight(MIN_IMG_HEIGHT); + imageView.setMinimumWidth(MIN_IMG_WIDTH); + task.execute(url); + break; + } + } + } + + /** + * Returns true if the current download has been canceled or if there was no + * download in progress on this image view. Returns false if the download in + * progress deals with the same url. The download is not stopped in that + * case. + */ + private static boolean cancelPotentialDownload(String url, + ImageView imageView) { + BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView); + + if (bitmapDownloaderTask != null) { + String bitmapUrl = bitmapDownloaderTask.url; + if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) { + bitmapDownloaderTask.cancel(true); + } else { + // The same URL is already being downloaded. + return false; + } + } + return true; + } + + /** + * @param imageView + * Any imageView + * @return Retrieve the currently active download task (if any) associated + * with this imageView. null if there is no such task. + */ + private static BitmapDownloaderTask getBitmapDownloaderTask( + ImageView imageView) { + if (imageView != null) { + Drawable drawable = imageView.getDrawable(); + if (drawable instanceof DownloadedDrawable) { + DownloadedDrawable downloadedDrawable = (DownloadedDrawable) drawable; + return downloadedDrawable.getBitmapDownloaderTask(); + } + } + return null; + } + + Bitmap downloadBitmap(String url) { + final int IO_BUFFER_SIZE = 4 * 1024; + + // AndroidHttpClient is not allowed to be used from the main thread + final HttpClient client = (mode == Mode.NO_ASYNC_TASK) ? new DefaultHttpClient() + : AndroidHttpClient.newInstance("Android"); + + HttpGet getRequest = null; + try { + getRequest = new HttpGet(url); + } catch (Exception e) { + if ((client instanceof AndroidHttpClient)) { + ((AndroidHttpClient) client).close(); + } + return null; + } + + try { + HttpResponse response = client.execute(getRequest); + final int statusCode = response.getStatusLine().getStatusCode(); + if (statusCode != HttpStatus.SC_OK) { + Log.w("ImageDownloader", "Error " + statusCode + + " while retrieving bitmap from " + url); + return null; + } + + final HttpEntity entity = response.getEntity(); + if (entity != null) { + InputStream inputStream = null; + try { + inputStream = entity.getContent(); + // return BitmapFactory.decodeStream(inputStream); + // Bug on slow connections, fixed in future release. + return BitmapFactory.decodeStream(new FlushedInputStream( + inputStream)); + } finally { + if (inputStream != null) { + inputStream.close(); + } + entity.consumeContent(); + } + } + } catch (IOException e) { + getRequest.abort(); + Log.w(LOG_TAG, "I/O error while retrieving bitmap from " + url, e); + } catch (IllegalStateException e) { + getRequest.abort(); + Log.w(LOG_TAG, "Incorrect URL: " + url); + } catch (Exception e) { + getRequest.abort(); + Log.w(LOG_TAG, "Error while retrieving bitmap from " + url, e); + } finally { + if ((client instanceof AndroidHttpClient)) { + ((AndroidHttpClient) client).close(); + } + } + return null; + } + + /* + * An InputStream that skips the exact number of bytes provided, unless it + * reaches EOF. + */ + static class FlushedInputStream extends FilterInputStream { + public FlushedInputStream(InputStream inputStream) { + super(inputStream); + } + + @Override + public long skip(long n) throws IOException { + long totalBytesSkipped = 0L; + while (totalBytesSkipped < n) { + long bytesSkipped = in.skip(n - totalBytesSkipped); + if (bytesSkipped == 0L) { + int b = read(); + if (b < 0) { + break; // we reached EOF + } else { + bytesSkipped = 1; // we read one byte + } + } + totalBytesSkipped += bytesSkipped; + } + return totalBytesSkipped; + } + } + + /** + * The actual AsyncTask that will asynchronously download the image. + */ + class BitmapDownloaderTask extends AsyncTask { + private String url; + private final WeakReference imageViewReference; + + public BitmapDownloaderTask(ImageView imageView) { + imageViewReference = new WeakReference(imageView); + } + + /** + * Actual download method. + */ + @Override + protected Bitmap doInBackground(String... params) { + url = params[0]; + return downloadBitmap(url); + } + + /** + * Once the image is downloaded, associates it to the imageView + */ + @Override + protected void onPostExecute(Bitmap bitmap) { + if (isCancelled()) { + bitmap = null; + } + + addBitmapToCache(url, bitmap); + + if (imageViewReference != null) { + ImageView imageView = imageViewReference.get(); + BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView); + // Change bitmap only if this process is still associated with + // it + // Or if we don't use any bitmap to task association + // (NO_DOWNLOADED_DRAWABLE mode) + if ((this == bitmapDownloaderTask) || (mode != Mode.CORRECT)) { + Bitmap newScaledBitmap = null; + if (bitmap != null && scale == true) { + newScaledBitmap = Bitmap.createScaledBitmap(bitmap, + bitmap_width, bitmap_height, true); + imageView.setImageBitmap(newScaledBitmap); + } else { + imageView.setImageBitmap(bitmap); + } + } + + if (bitmap == null) { + if (imageView != null) + imageView.setImageResource(R.drawable.no_image); + } + } + + } + } + + /** + * A fake Drawable that will be attached to the imageView while the download + * is in progress. + * + *

+ * Contains a reference to the actual download task, so that a download task + * can be stopped if a new binding is required, and makes sure that only the + * last started download process can bind its result, independently of the + * download finish order. + *

+ */ + static class DownloadedDrawable extends ColorDrawable { + private final WeakReference bitmapDownloaderTaskReference; + + public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) { + super(Color.BLACK); + + bitmapDownloaderTaskReference = new WeakReference( + bitmapDownloaderTask); + } + + public BitmapDownloaderTask getBitmapDownloaderTask() { + return bitmapDownloaderTaskReference.get(); + } + } + + public void setMode(Mode mode) { + this.mode = mode; + clearCache(); + } + + /* + * Cache-related fields and methods. + * + * We use a hard and a soft cache. A soft reference cache is too + * aggressively cleared by the Garbage Collector. + */ + + private static final int HARD_CACHE_CAPACITY = 20; + private static final int DELAY_BEFORE_PURGE = 10 * 1000; // in milliseconds + + // Hard cache, with a fixed maximum capacity and a life duration + private final HashMap sHardBitmapCache = new LinkedHashMap( + HARD_CACHE_CAPACITY / 2, 0.75f, true) { + @Override + protected boolean removeEldestEntry( + LinkedHashMap.Entry eldest) { + if (size() > HARD_CACHE_CAPACITY) { + // Entries push-out of hard reference cache are transferred to + // soft reference cache + sSoftBitmapCache.put(eldest.getKey(), + new SoftReference(eldest.getValue())); + return true; + } else + return false; + } + }; + + // Soft cache for bitmaps kicked out of hard cache + private final static ConcurrentHashMap> sSoftBitmapCache = new ConcurrentHashMap>( + HARD_CACHE_CAPACITY / 2); + + private final Handler purgeHandler = new Handler(); + + private final Runnable purger = new Runnable() { + public void run() { + clearCache(); + } + }; + + /** + * Adds this bitmap to the cache. + * + * @param bitmap + * The newly downloaded bitmap. + */ + private void addBitmapToCache(String url, Bitmap bitmap) { + if (bitmap != null) { + synchronized (sHardBitmapCache) { + sHardBitmapCache.put(url, bitmap); + } + } + } + + /** + * @param url + * The URL of the image that will be retrieved from the cache. + * @return The cached bitmap or null if it was not found. + */ + private Bitmap getBitmapFromCache(String url) { + // First try the hard reference cache + synchronized (sHardBitmapCache) { + final Bitmap bitmap = sHardBitmapCache.get(url); + if (bitmap != null) { + // Bitmap found in hard cache + // Move element to first position, so that it is removed last + sHardBitmapCache.remove(url); + sHardBitmapCache.put(url, bitmap); + return bitmap; + } + } + + // Then try the soft reference cache + SoftReference bitmapReference = sSoftBitmapCache.get(url); + if (bitmapReference != null) { + final Bitmap bitmap = bitmapReference.get(); + if (bitmap != null) { + // Bitmap found in soft cache + return bitmap; + } else { + // Soft reference has been Garbage Collected + sSoftBitmapCache.remove(url); + } + } + + return null; + } + + /** + * Clears the image cache used internally to improve performance. Note that + * for memory efficiency reasons, the cache will automatically be cleared + * after a certain inactivity delay. + */ + public void clearCache() { + sHardBitmapCache.clear(); + sSoftBitmapCache.clear(); + } + + /** + * Allow a new delay before the automatic cache clear is done. + */ + private void resetPurgeTimer() { + purgeHandler.removeCallbacks(purger); + purgeHandler.postDelayed(purger, DELAY_BEFORE_PURGE); + } +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/MoreCopyInformation.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/MoreCopyInformation.java new file mode 100644 index 0000000000..d721cb33ba --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/MoreCopyInformation.java @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.searchCatalog; + +import java.util.Iterator; +import java.util.Set; +import java.util.Map.Entry; + +import org.evergreen_ils.R; +import org.evergreen_ils.globals.GlobalConfigs; +import org.evergreen_ils.views.AccountScreenDashboard; +import org.evergreen_ils.views.splashscreen.SplashActivity; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup.LayoutParams; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.TextView; + +public class MoreCopyInformation extends Activity { + + private Button homeButton; + + private Button myAccountButton; + + private TextView headerTitle; + + private Context context; + + private RecordInfo record; + + private GlobalConfigs gl; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (!SplashActivity.isAppInitialized()) { + SplashActivity.restartApp(this); + return; + } + + setContentView(R.layout.copy_information_more); + gl = GlobalConfigs.getGlobalConfigs(context); + context = this; + record = (RecordInfo) getIntent().getSerializableExtra("recordInfo"); + + // header portion actions + myAccountButton = (Button) findViewById(R.id.my_account_button); + myAccountButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getApplicationContext(), + AccountScreenDashboard.class); + startActivity(intent); + } + }); + + homeButton = (Button) findViewById(R.id.action_bar_home_button); + homeButton.setText(R.string.copy_information_title); + homeButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getApplicationContext(), + SearchCatalogListView.class); + startActivity(intent); + } + }); + // end header portion actions + + LayoutInflater inf = (LayoutInflater) context + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + + // insert into main view + LinearLayout insertPoint = (LinearLayout) findViewById(R.id.record_details_copy_information); + addCopyInfo(inf, insertPoint); + + } + + public void addCopyInfo(LayoutInflater inflater, LinearLayout insertPoint) { + + for (int i = 0; i < record.copyInformationList.size(); i++) { + + View copy_info_view = inflater.inflate(R.layout.copy_information, + null); + + // fill in any details dynamically here + TextView library = (TextView) copy_info_view + .findViewById(R.id.copy_information_library); + TextView call_number = (TextView) copy_info_view + .findViewById(R.id.copy_information_call_number); + TextView copy_location = (TextView) copy_info_view + .findViewById(R.id.copy_information_copy_location); + + library.setText(gl.getOrganizationName(record.copyInformationList + .get(i).org_id) + " "); + call_number + .setText(record.copyInformationList.get(i).call_number_sufix); + copy_location + .setText(record.copyInformationList.get(i).copy_location); + + // insert into main view + insertPoint.addView(copy_info_view, new ViewGroup.LayoutParams( + LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT)); + + LinearLayout copy_statuses = (LinearLayout) copy_info_view + .findViewById(R.id.copy_information_statuses); + + CopyInformation info = record.copyInformationList.get(i); + + Set> set = info.statusInformation.entrySet(); + + Iterator> it = set.iterator(); + + while (it.hasNext()) { + + Entry ent = it.next(); + TextView statusName = new TextView(context); + statusName.setText(ent.getKey() + " : " + ent.getValue()); + + copy_statuses.addView(statusName, new LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); + + } + + } + + } +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/Organisation.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/Organisation.java new file mode 100644 index 0000000000..15ee726761 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/Organisation.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.searchCatalog; + +public class Organisation { + + public String name = null; + + public String shortName = null; + + public Integer id = null; + + public Integer level = null; + + public Integer parent = null; + + public Integer isVisible = null; + + public Integer hiddenDepth = null; + + // used for indent display + public String padding = ""; + + public Organisation() { + + } +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/RecordInfo.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/RecordInfo.java new file mode 100644 index 0000000000..402a20337c --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/RecordInfo.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.searchCatalog; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import android.util.Log; +import org.opensrf.util.OSRFObject; + +public class RecordInfo implements Serializable { + + // {"title","author","doc_id","doc_type","pubdate","isbn","publisher","tcn","subject","type_of_resources","call_numbers","edition","online_loc","synopsis","physical_description","toc","copy_count","series","serials","foreign_copy_maps"}); + + private static final long serialVersionUID = 10123L; + + private final String TAG = RecordInfo.class.getName(); + + public String title = null; + + public String author = null; + + public String pubdate = null; + + public String isbn = null; + + public Integer doc_id = null; + + public String publisher = null; + + public String subject = null; + + public String doc_type = null; + + public String online_loc = null; + + public String synopsis = null; + + public String physical_description = null; + + public String series = null; + + // tcn field + public String image = null; + + public boolean dummy = false; + + public ArrayList copyCountListInfo = null; + + public List copyInformationList = null; + + public RecordInfo() { + this.title = "Test title"; + this.author = "Test author"; + this.pubdate = "Publication date"; + copyInformationList = new ArrayList(); + + // marks the fact that this is a record made from no info + this.dummy = true; + } + + public RecordInfo(OSRFObject info) { + copyInformationList = new ArrayList(); + try { + + this.title = info.getString("title"); + this.author = info.getString("author"); + this.pubdate = info.getString("pubdate"); + this.publisher = info.getString("publisher"); + this.doc_id = info.getInt("doc_id"); + this.image = info.getString("tcn"); + this.doc_type = info.getString("doc_type"); + } catch (Exception e) { + Log.d(TAG, "Exception basic info " + e.getMessage()); + } + ; + + try { + this.isbn = (String) info.get("isbn"); + } catch (Exception e) { + Log.d(TAG, "Exception isbn " + e.getMessage()); + } + ; + + try { + + Map subjectMap = (Map) info.get("subject"); + + this.subject = ""; + + int no = subjectMap.entrySet().size(); + int i = 0; + for (Entry entry : subjectMap.entrySet()) { + i++; + if (i < no) + this.subject += entry.getKey() + " \n"; + else + this.subject += entry.getKey(); + } + + } catch (Exception e) { + Log.d(TAG, "Exception subject " + e.getMessage()); + } + ; + try { + + this.online_loc = ((List) info.get("online_loc")).get(0).toString(); + + } catch (Exception e) { + Log.d(TAG, "Exception online_loc " + e.getMessage()); + } + ; + try { + this.physical_description = (String) info + .get("physical_description"); + } catch (Exception e) { + Log.d(TAG, "Exception physical_description " + + e.getMessage()); + } + ; + try { + this.series = ""; + List seriesList = (List) info.get("series"); + for (int i = 0; i < seriesList.size(); i++) + if (i < seriesList.size() - 1) + this.series += seriesList.get(i) + ", "; + else + this.series += seriesList.get(i); + } catch (Exception e) { + Log.d(TAG, "Exception series " + e.getMessage()); + } + ; + + } +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/SampleUnderlinesNoFade.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/SampleUnderlinesNoFade.java new file mode 100644 index 0000000000..0633d21baf --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/SampleUnderlinesNoFade.java @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.searchCatalog; + +import java.util.ArrayList; + +import org.evergreen_ils.R; +import org.evergreen_ils.utils.ui.BaseSampleActivity; +import org.evergreen_ils.utils.ui.BasicDetailsFragment; +import org.evergreen_ils.utils.ui.TestFragmentAdapter; +import org.evergreen_ils.utils.ui.UnderlinePageIndicator; +import org.evergreen_ils.views.AccountScreenDashboard; +import org.evergreen_ils.views.splashscreen.SplashActivity; + +import android.app.ProgressDialog; +import android.content.Context; +import android.content.Intent; +import android.net.ConnectivityManager; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.view.ViewPager; +import android.view.KeyEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.TextView; + +public class SampleUnderlinesNoFade extends BaseSampleActivity { + + private ArrayList records; + + private Button myAccountButton; + + private Button homeButton; + + private TextView headerTitle; + + private SearchCatalog search; + + private ArrayList searchRecords; + + private Context context; + + private ProgressDialog progressDialog; + + private Runnable searchRunnableWithOffset; + + public static final int RETURN_DATA = 5; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (!SplashActivity.isAppInitialized()) { + SplashActivity.restartApp(this); + return; + } + + setContentView(R.layout.simple_underlines); + + search = SearchCatalog.getInstance((ConnectivityManager)getSystemService(CONNECTIVITY_SERVICE)); + + records = (ArrayList) getIntent().getSerializableExtra( + "recordList"); + + if (records.get(records.size() - 1).dummy == true) + records.remove(records.size() - 1); + + context = this; + + // header portion actions + homeButton = (Button) findViewById(R.id.action_bar_home_button); + myAccountButton = (Button) findViewById(R.id.my_account_button); + + myAccountButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getApplicationContext(), + AccountScreenDashboard.class); + startActivity(intent); + } + }); + + homeButton.setText(R.string.search_details_title); + homeButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getApplicationContext(), + SearchCatalogListView.class); + startActivity(intent); + } + }); + // end header portion actions + + int record_position = getIntent().getIntExtra("recordPosition", 0); + mAdapter = new SearchFragmentAdapter(getSupportFragmentManager()); + + mPager = (ViewPager) findViewById(R.id.pager); + mPager.setAdapter(mAdapter); + + mPager.setCurrentItem(record_position); + + UnderlinePageIndicator indicator = (UnderlinePageIndicator) findViewById(R.id.indicator); + indicator.setViewPager(mPager); + indicator.setFades(false); + mIndicator = indicator; + searchRunnableWithOffset = new Runnable() { + + @Override + public void run() { + + runOnUiThread(new Runnable() { + + @Override + public void run() { + progressDialog = ProgressDialog.show(context, null,getResources().getText(R.string.dialog_load_more_message)); + } + }); + + searchRecords = search.getSearchResults(search.searchText, records.size()); + + runOnUiThread(new Runnable() { + + @Override + public void run() { + // don't clear record list + // recordList.clear(); + if (searchRecords.size() > 0) { + + for (int j = 0; j < searchRecords + .size(); j++) + records.add(searchRecords.get(j)); + + // add extra record to display more + // option button + + } + progressDialog.dismiss(); + } + }); + + } + }; + + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + Intent intent = new Intent(); + intent.putExtra("recordList", records); + setResult(RETURN_DATA, intent); + finish(); + + return true; + } + return super.onKeyDown(keyCode, event); + } + + + class SearchFragmentAdapter extends TestFragmentAdapter { + public SearchFragmentAdapter(FragmentManager fm) { + super(fm); + } + + @Override + public Fragment getItem(int position) { + // position +1 for 1 - size values + + if(position == records.size() - 1 && records.size() < search.visible){ + Thread getSearchResults = new Thread(searchRunnableWithOffset); + getSearchResults.start(); + } + return BasicDetailsFragment.newInstance(records.get(position), + position + 1, search.visible); + + } + + @Override + public int getCount() { + return records.size(); + // return TabsView.CONTENT.length; + } + + } +} \ No newline at end of file diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/SearchCatalog.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/SearchCatalog.java new file mode 100644 index 0000000000..71760d39cc --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/SearchCatalog.java @@ -0,0 +1,394 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.searchCatalog; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.evergreen_ils.globals.GlobalConfigs; +import org.evergreen_ils.globals.Utils; +import org.opensrf.Method; +import org.opensrf.net.http.GatewayRequest; +import org.opensrf.net.http.HttpConnection; +import org.opensrf.net.http.HttpRequest; +import org.opensrf.net.http.HttpRequestHandler; +import org.opensrf.util.OSRFObject; + +import android.net.ConnectivityManager; +import android.util.Log; + +/** + * The Class SearchCatalog. + */ +public class SearchCatalog { + + /** The SERVICE. */ + public static String SERVICE = "open-ils.search"; + + /** The METHO d_ multicas s_ search. */ + public static String METHOD_MULTICLASS_QUERY = "open-ils.search.biblio.multiclass.query"; + + /** The METHO d_ sli m_ retrive. */ + public static String METHOD_SLIM_RETRIVE = "open-ils.search.biblio.record.mods_slim.retrieve"; + + /** + * Method + * + * @param : no parameters + * @returns : returns array of ccs objects + */ + + public static String METHOD_COPY_STATUS_ALL = "open-ils.search.config.copy_status.retrieve.all"; + + /** + * Method that returns library where record with id is + * + * @param : record ID to get all libraries, or just book ID, Current Library + * ID, User ID + * @returns : + * [[["4","","CONCERTO 27","","Stacks",{"0":5}],["4","","PERFORM 27" + * ,"","Stacks",{"0":2}]]] "0":% is the available books [org_id, + * call_number_sufix, copy_location, status1:count, status2:count + * ..] + */ + public static String METHOD_COPY_LOCATION_COUNTS = "open-ils.search.biblio.copy_location_counts.summary.retrieve"; + + /** + * Get copy statuses like Available, Checked_out , in_progress and others, + * ccs OSRFObjects + */ + public static String METHOD_GET_COPY_STATUSES = "open-ils.search.config.copy_status.retrieve.all"; + + /** + * Get copy count information + * + * @param : org_unit_id, record_id, "" ? + * @returns: objects + * [{"transcendant":null,"count":35,"org_unit":1,"depth":0, + * "unshadow":35,"available":35}, + * {"transcendant":null,"count":14,"org_unit" + * :2,"depth":1,"unshadow" + * :14,"available":14},{"transcendant":null, + * "count":7,"org_unit":4,"depth":2,"unshadow":7,"available":7}] + */ + public static String METHOD_GET_COPY_COUNT = "open-ils.search.biblio.record.copy_count"; + + public static SearchCatalog searchCatalogSingleton = null; + /** The conn. */ + public HttpConnection conn; + + // TODO get statuses on load + // open-ils.search.config.copy_status.retrieve.all + + /** The TAG. */ + public String TAG = "SearchCatalog"; + + // the org on witch the searches will be made + /** The selected organization. */ + public Organisation selectedOrganization = null; + + public Integer offset; + + public Integer visible; + + public Integer searchLimit = 10; + + public String searchText = null; + + private ConnectivityManager cm; + + public static SearchCatalog getInstance(ConnectivityManager cm) { + + if (searchCatalogSingleton == null) { + searchCatalogSingleton = new SearchCatalog(cm); + } + + return searchCatalogSingleton; + } + + public static SearchCatalog getInstance() { + + return searchCatalogSingleton; + } + + /** + * Instantiates a new search catalog. + */ + private SearchCatalog(ConnectivityManager cm) { + super(); + + this.cm = cm; + + try { + // configure the connection + conn = new HttpConnection(GlobalConfigs.httpAddress + + "/osrf-gateway-v1"); + + } catch (Exception e) { + System.err.println("Exception in establishing connection " + + e.getMessage()); + } + // registering classes so no longer necessary to register object classes + // manually + + } + + /** + * Gets the search results + * + * @param searchWords + * the search words + * @return the search results + */ + public ArrayList getSearchResults(String searchWords, + Integer offset) { + + searchText = searchWords; + + ArrayList resultsRecordInfo = new ArrayList(); + + Method method = new Method(METHOD_MULTICLASS_QUERY); + + HashMap complexParm = new HashMap(); + + try { + //KCXXX I'm not too sure about this depth option + if (this.selectedOrganization != null) { + if (this.selectedOrganization.id != null) + complexParm.put("org_unit", this.selectedOrganization.id); + if (this.selectedOrganization.level != null) + complexParm.put("depth", + this.selectedOrganization.level - 1); + } + // TODO change here, multiple result per page + complexParm.put("limit", searchLimit); + + complexParm.put("offset", offset); + + /* + * complexParm.put("offset",0); complexParm.put("visibility_limit", + * 3000); complexParm.put("default_class","keyword"); + */ + + } catch (Exception e) { + Log.d(TAG, "Exception in JSON " + e.getMessage()); + } + + // do request and check for connectivity + Object resp = Utils.doRequest(conn, SERVICE, METHOD_MULTICLASS_QUERY, + cm, new Object[] { complexParm, searchWords, 1 }); + + ArrayList ids = new ArrayList(); + + Log.d(TAG, "Sync Response: " + resp); + if (resp == null) + return resultsRecordInfo; // search failed or server crashed + + Map response = (Map) resp; + + Log.d(TAG, " ids : " + response.get("ids") + " "); + + List> result_ids; + result_ids = (List>) response.get("ids"); + Log.d(TAG, "length:"+result_ids.size()); + + // sometimes count is an int ("count":0) and sometimes string ("count":"1103") + visible = Integer.parseInt(response.get("count").toString()); + + for (int i = 0; i < result_ids.size(); i++) { + ids.add(result_ids.get(i).get(0)); + } + + Log.d(TAG, "Ids " + ids); + + // request other info based on ids + + for (int i = 0; i < ids.size(); i++) { + + RecordInfo record = new RecordInfo( + getItemShortInfo(Integer.parseInt(ids.get(i)))); + // get copy information + resultsRecordInfo.add(record); + + record.copyCountListInfo = getCopyCount( + Integer.parseInt(ids.get(i)), this.selectedOrganization.id); + + // get copy count + List> list = (List>) getLocationCount( + Integer.parseInt(ids.get(i)), this.selectedOrganization.id, + this.selectedOrganization.level - 1); + + if (list != null) + for (int j = 0; j < list.size(); j++) { + CopyInformation copyInfo = new CopyInformation(list.get(j)); + + record.copyInformationList.add(copyInfo); + } + + Log.d(TAG, "Title " + record.title + " Author " + + record.author + " Pub date" + record.pubdate + + " Publisher" + record.publisher); + } + + return resultsRecordInfo; + } + + /** + * Gets the item short info. + * + * @param id + * the id + * @return the item short info + */ + private OSRFObject getItemShortInfo(Integer id) { + + Method method = new Method(METHOD_SLIM_RETRIVE); + + method.addParam(id); + + HttpRequest req = new GatewayRequest(conn, SERVICE, method).send(); + Object resp; + while ((resp = req.recv()) != null) { + Log.d(TAG, "Sync Response: " + resp); + return (OSRFObject) resp; + } + + return null; + } + + /** + * Search catalog. + * + * @param searchWords + * the search words + * @return the object + */ + public Object searchCatalog(String searchWords) { + + Object response = Utils.doRequest(conn, SERVICE, METHOD_SLIM_RETRIVE, + cm, new Object[] { "keyword", searchWords }); + + return response; + + } + + /** + * Search catalog. + * + * @param searchWords + * the search words + * @param requestHandler + * the request handler + */ + public void searchCatalog(String searchWords, + HttpRequestHandler requestHandler) { + + Method method = new Method(METHOD_SLIM_RETRIVE); + + method.addParam(searchWords); + + // sync test + HttpRequest req = new GatewayRequest(conn, SERVICE, method).send(); + req.sendAsync(requestHandler); + + } + + public Object getCopyStatuses() { + + List ccs_list = (List) Utils.doRequestSimple( + conn, SERVICE, METHOD_COPY_STATUS_ALL, new Object[] {}); + + CopyInformation.availableOrgStatuses = new LinkedHashMap(); + + if (ccs_list != null) { + for (int i = 0; i < ccs_list.size(); i++) { + OSRFObject ccs_obj = ccs_list.get(i); + if (ccs_obj.getString("opac_visible").equals("t")) { + CopyInformation.availableOrgStatuses.put( + ccs_obj.getInt("id") + "", + ccs_obj.getString("name")); + //Log.d(TAG, "Add status "+ccs_obj.getString("name")); + } + } + } + return ccs_list; + } + + public Object getLocationCount(Integer recordID, Integer orgID, + Integer orgDepth) { + + List list = (List) Utils.doRequestSimple(conn, SERVICE, + METHOD_COPY_LOCATION_COUNTS, new Object[] { recordID, orgID, + orgDepth }); + return list; + + } + + public ArrayList getRecordsInfo(ArrayList ids) { + + ArrayList recordInfoArray = new ArrayList(); + + for (int i = 0; i < ids.size(); i++) { + RecordInfo recordInfo = new RecordInfo(getItemShortInfo(ids.get(i))); + recordInfoArray.add(recordInfo); + } + + return recordInfoArray; + } + + /** + * Select organisation. + * + * @param org + * the organization on witch the searches will be made + */ + public void selectOrganisation(Organisation org) { + + Log.d(TAG, "Select search organisation " + (org.level - 1) + " " + + org.id); + this.selectedOrganization = org; + + } + + public ArrayList getCopyCount(Integer recordID, + Integer orgID) { + + List list = (List) Utils.doRequestSimple(conn, SERVICE, + METHOD_GET_COPY_COUNT, new Object[] { orgID, recordID, "" }); + + ArrayList copyInfoList = new ArrayList(); + + if (list == null) + return copyInfoList; + + for (int i = 0; i < list.size(); i++) { + + CopyCountInformation copyInfo = new CopyCountInformation( + list.get(i)); + copyInfoList.add(copyInfo); + } + + return copyInfoList; + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/SearchCatalogListView.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/SearchCatalogListView.java new file mode 100644 index 0000000000..776f3be4da --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/searchCatalog/SearchCatalogListView.java @@ -0,0 +1,795 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.searchCatalog; + +import java.util.ArrayList; +import java.util.List; + +import org.evergreen_ils.R; +import org.evergreen_ils.R.layout; +import org.evergreen_ils.accountAccess.AccountAccess; +import org.evergreen_ils.accountAccess.SessionNotFoundException; +import org.evergreen_ils.accountAccess.bookbags.BookBag; +import org.evergreen_ils.accountAccess.holds.PlaceHold; +import org.evergreen_ils.barcodescan.CaptureActivity; +import org.evergreen_ils.globals.GlobalConfigs; +import org.evergreen_ils.views.AccountScreenDashboard; +import org.evergreen_ils.views.ApplicationPreferences; +import org.evergreen_ils.views.splashscreen.SplashActivity; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.Intent; +import android.net.ConnectivityManager; +import android.os.Bundle; +import android.util.Log; +import android.view.ContextMenu; +import android.view.ContextMenu.ContextMenuInfo; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.View.OnKeyListener; +import android.view.ViewGroup; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; +import android.widget.AbsListView; +import android.widget.AbsListView.OnScrollListener; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.AdapterView.OnItemSelectedListener; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.Spinner; +import android.widget.TextView; +import android.widget.Toast; + +public class SearchCatalogListView extends Activity { + + private final String TAG = SearchCatalogListView.class.getName(); + + private ArrayList recordList; + + private EditText searchText; + + private ImageButton searchButton; + + private SearchCatalog search; + + private ListView lv; + + private SearchArrayAdapter adapter; + + private Context context; + + private ProgressDialog progressDialog; + + private ArrayList searchResults; + + private Spinner choseOrganisation; + + private GlobalConfigs globalConfigs; + + private static final int PLACE_HOLD = 0; + + private static final int DETAILS = 1; + + private static final int BOOK_BAG = 2; + + private TextView searchResultsNumber; + + private ArrayList bookBags; + + private Integer bookbag_selected = -1; + + private final ImageDownloader imageDownloader = new ImageDownloader(); + + private Runnable searchForResultsRunnable = null; + + private View searchOptionsMenu = null; + + private Button advancedSearchButton = null; + + private Button libraryHoursButton = null; + + private Button preferenceButton = null; + + private Button barcodeScanButton = null; + + private Button homeButton = null; + + private Button myAccountButton = null; + + private String advancedSearchString = null; + + // marks when the fetching record thread is started + private boolean loadingElements = false; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (!SplashActivity.isAppInitialized()) { + SplashActivity.restartApp(this); + return; + } + + setContentView(R.layout.search_result_list); + setTitle(R.string.browse_catalog); + + myAccountButton = (Button) findViewById(R.id.my_account_button); + myAccountButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getApplicationContext(), + AccountScreenDashboard.class); + startActivity(intent); + } + }); + + homeButton = (Button) findViewById(R.id.action_bar_home_button); + homeButton.setText(R.string.browse_catalog); + homeButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + searchOptionsMenu.setVisibility(View.VISIBLE); + searchResultsNumber.setVisibility(View.INVISIBLE); + } + }); + // end header portion actions + + advancedSearchButton = (Button) findViewById(R.id.menu_advanced_search_button); + advancedSearchButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + // show advanced view dialog + Intent advancedSearch = new Intent(context, + AdvancedSearchActivity.class); + startActivityForResult(advancedSearch, 2); + } + }); + // get bookbags + bookBags = AccountAccess.getAccountAccess().getBookbags(); + + libraryHoursButton = (Button) findViewById(R.id.library_hours_button); + libraryHoursButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + // TODO Auto-generated method stub + } + }); + + preferenceButton = (Button) findViewById(R.id.preference_button); + preferenceButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getApplicationContext(), + ApplicationPreferences.class); + startActivity(intent); + } + }); + + barcodeScanButton = (Button) findViewById(R.id.barcode_scan_button); + barcodeScanButton.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + Intent barcodeScan = new Intent(getApplicationContext(), + CaptureActivity.class); + startActivityForResult(barcodeScan, 10); + } + }); + // singleton initialize necessary IDL and Org data + globalConfigs = GlobalConfigs.getGlobalConfigs(this); + + context = this; + search = SearchCatalog + .getInstance((ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE)); + + recordList = new ArrayList(); + + // Create a customized ArrayAdapter + adapter = new SearchArrayAdapter(getApplicationContext(), + R.layout.search_result_item, recordList); + + searchResultsNumber = (TextView) findViewById(R.id.search_result_number); + + // Get reference to ListView holder + lv = (ListView) this.findViewById(R.id.search_results_list); + + searchOptionsMenu = findViewById(R.id.search_preference_options); + + progressDialog = new ProgressDialog(context); + + // Set the ListView adapter + lv.setAdapter(adapter); + + searchResults = new ArrayList(); + + registerForContextMenu(lv); + + searchForResultsRunnable = new Runnable() { + + @Override + public void run() { + + final String text = searchText.getText().toString(); + if (text.length() < 1) + return; + + runOnUiThread(new Runnable() { + @Override + public void run() { + + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow( + searchText.getWindowToken(), 0); + + searchOptionsMenu.setVisibility(View.GONE); + searchResultsNumber.setVisibility(View.VISIBLE); + + progressDialog = ProgressDialog.show( + context, + getResources().getText(R.string.dialog_please_wait), + getResources().getText( + R.string.dialog_fetching_data_message)); + } + }); + + searchResults = search.getSearchResults(text, 0); + + runOnUiThread(new Runnable() { + + @Override + public void run() { + + recordList.clear(); + + if (searchResults.size() > 0) { + + for (int j = 0; j < searchResults.size(); j++) + recordList.add(searchResults.get(j)); + + // add extra record to display more option button + /* + * if (search.visible > recordList.size()) { + * recordList.add(new RecordInfo()); + * searchResultsNumber.setText(+recordList.size() - + * 1 + " out of " + search.visible); } else + */ + } + searchResultsNumber.setText(+recordList.size() + + " out of " + search.visible); + + adapter.notifyDataSetChanged(); + progressDialog.dismiss(); + + } + }); + + } + }; + + lv.setOnItemClickListener(new OnItemClickListener() { + + @Override + public void onItemClick(AdapterView arg0, View arg1, + int position, long arg3) { + + RecordInfo info = (RecordInfo) lv.getItemAtPosition(position); + + if (info.dummy == true) { + // this is the more view item button + progressDialog = new ProgressDialog(context); + + progressDialog.setMessage("Fetching data"); + progressDialog.show(); + final String text = searchText.getText().toString(); + + Thread searchThreadwithOffset = new Thread(new Runnable() { + + @Override + public void run() { + + searchResults.clear(); + + searchResults = search.getSearchResults(text, + recordList.size()); + + runOnUiThread(new Runnable() { + + @Override + public void run() { + + // don't clear record list + // recordList.clear(); + if (searchResults.size() > 0) { + + // remove previous more button + recordList.remove(recordList.size() - 1); + + for (int j = 0; j < searchResults + .size(); j++) + recordList.add(searchResults.get(j)); + + // add extra record to display more + // option button + if (search.visible > recordList.size()) { + recordList.add(new RecordInfo()); + searchResultsNumber.setText(adapter + .getCount() + - 1 + + " out of " + + search.visible); + } else + searchResultsNumber.setText(adapter + .getCount() + + " out of " + + search.visible); + } else { + searchResultsNumber.setText(adapter + .getCount() + + " out of " + + search.visible); + } + adapter.notifyDataSetChanged(); + progressDialog.dismiss(); + } + }); + + } + }); + + searchThreadwithOffset.start(); + } else { + // start activity with book details + + Intent intent = new Intent(getBaseContext(), + SampleUnderlinesNoFade.class); + // serialize object and pass it to next activity + intent.putExtra("recordInfo", info); + intent.putExtra("orgID", search.selectedOrganization.id); + intent.putExtra("depth", (search.selectedOrganization.level - 1)); + intent.putExtra("recordList", recordList); + intent.putExtra("recordPosition", position); + startActivityForResult(intent, 10); + } + } + }); + + lv.setOnScrollListener(new OnScrollListener() { + + @Override + public void onScrollStateChanged(AbsListView view, int scrollState) { + // TODO Auto-generated method stub + + } + + @Override + public void onScroll(AbsListView view, int firstVisibleItem, + int visibleItemCount, int totalItemCount) { + + if (!loadingElements) { + + /* + Log.d(TAG, " Scroll adapter " + totalItemCount + " " + + visibleItemCount + " " + firstVisibleItem + " " + + adapter.getCount() + " " + search.visible); + */ + if (totalItemCount > 0 + && (((totalItemCount - visibleItemCount) <= (firstVisibleItem)) && adapter + .getCount() < search.visible)) { + loadingElements = true; + Log.d(TAG, "Load more data"); + progressDialog = new ProgressDialog(context); + + progressDialog.setMessage(getResources().getText( + R.string.dialog_load_more_message)); + progressDialog.show(); + + Thread searchThreadwithOffset = new Thread( + new Runnable() { + + @Override + public void run() { + + String text = searchText.getText() + .toString(); + searchResults.clear(); + + searchResults = search + .getSearchResults(text, + adapter.getCount()); + + runOnUiThread(new Runnable() { + + @Override + public void run() { + + // don't clear record list + // recordList.clear(); + Log.d(TAG, "Returned " + + searchResults.size() + + " elements from search"); + if (searchResults.size() > 0) { + + for (int j = 0; j < searchResults + .size(); j++) + recordList + .add(searchResults + .get(j)); + + } + + searchResultsNumber.setText(adapter + .getCount() + + " out of " + + search.visible); + + adapter.notifyDataSetChanged(); + progressDialog.dismiss(); + loadingElements = false; + } + }); + + } + }); + + searchThreadwithOffset.start(); + } + } + } + }); + + searchText = (EditText) findViewById(R.id.searchText); + + // enter key now is labeled "Search" on virtual keyboard + searchText.setImeActionLabel("Search", EditorInfo.IME_ACTION_SEARCH); + searchText.setImeOptions(EditorInfo.IME_ACTION_SEARCH); + + // enter key on virtual keyboard starts the search + searchText.setOnKeyListener(new OnKeyListener() { + public boolean onKey(View v, int keyCode, KeyEvent event) { + // If the event is a key-down event on the "enter" button + if ((event.getAction() == KeyEvent.ACTION_DOWN) + && ((keyCode == KeyEvent.KEYCODE_ENTER) || keyCode == EditorInfo.IME_ACTION_SEARCH)) { + // Perform action on key press + Thread searchThread = new Thread(searchForResultsRunnable); + searchThread.start(); + return true; + } + return false; + } + }); + + + searchButton = (ImageButton) findViewById(R.id.searchButton); + searchButton.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + Thread searchThread = new Thread(searchForResultsRunnable); + searchThread.start(); + } + }); + + int selectedPos = 0; + int homeLibrary = 0; + if (AccountAccess.getAccountAccess() != null) { + homeLibrary = AccountAccess.getAccountAccess().getHomeLibraryID(); + } + ArrayList list = new ArrayList(); + Log.d(TAG, "Org scanning ..."); + if (globalConfigs.organisations != null) { + for (int i = 0; i < globalConfigs.organisations.size(); i++) { + Organisation org = globalConfigs.organisations.get(i); + list.add(org.padding + org.name); + if (org.id == homeLibrary) + selectedPos = i; + } + } + Log.d(TAG, "Org scanning ...done"); + ArrayAdapter adapter = new ArrayAdapter(this, + layout.spinner_layout, list); + choseOrganisation = (Spinner) findViewById(R.id.chose_organisation); + choseOrganisation.setAdapter(adapter); + choseOrganisation.setSelection(selectedPos); + choseOrganisation + .setOnItemSelectedListener(new OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView arg0, View arg1, + int ID, long arg3) { + // select the specific organization + search.selectOrganisation(globalConfigs.organisations + .get(ID)); + } + + @Override + public void onNothingSelected(AdapterView arg0) { + + } + + }); + + } + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, + ContextMenuInfo menuInfo) { + + Log.d(TAG, "context menu"); + if (v.getId() == R.id.search_results_list) { + + AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; + menu.setHeaderTitle("Options"); + + menu.add(Menu.NONE, DETAILS, 0, "Details"); + menu.add(Menu.NONE, PLACE_HOLD, 1, "Place Hold"); + menu.add(Menu.NONE, BOOK_BAG, 2, "Add to bookbag"); + + } + } + + @Override + public boolean onContextItemSelected(MenuItem item) { + AdapterView.AdapterContextMenuInfo menuArrayItem = (AdapterView.AdapterContextMenuInfo) item + .getMenuInfo(); + int menuItemIndex = item.getItemId(); + + final RecordInfo info = (RecordInfo) lv + .getItemAtPosition(menuArrayItem.position); + // start activity with book details + + switch (item.getItemId()) { + + case DETAILS: { + + Intent intent = new Intent(getBaseContext(), + SampleUnderlinesNoFade.class); + // serialize object and pass it to next activity + intent.putExtra("recordInfo", info); + intent.putExtra("orgID", search.selectedOrganization.id); + intent.putExtra("depth", (search.selectedOrganization.level - 1)); + + intent.putExtra("recordList", recordList); + // TODO put total number + intent.putExtra("recordPosition", menuArrayItem.position); + startActivity(intent); + } + break; + case PLACE_HOLD: { + + Intent intent = new Intent(getBaseContext(), PlaceHold.class); + + intent.putExtra("recordInfo", info); + + startActivity(intent); + } + break; + case BOOK_BAG: { + + if (bookBags.size() > 0) { + String array_spinner[] = new String[bookBags.size()]; + + for (int i = 0; i < array_spinner.length; i++) + array_spinner[i] = bookBags.get(i).name; + + AlertDialog.Builder builder; + + LayoutInflater inflater = (LayoutInflater) context + .getSystemService(LAYOUT_INFLATER_SERVICE); + View layout = inflater.inflate(R.layout.bookbag_spinner, null); + + Spinner s = (Spinner) layout.findViewById(R.id.bookbag_spinner); + + Button add = (Button) layout + .findViewById(R.id.add_to_bookbag_button); + ArrayAdapter adapter = new ArrayAdapter(context, + android.R.layout.simple_spinner_item, array_spinner); + + s.setAdapter(adapter); + builder = new AlertDialog.Builder(context); + builder.setView(layout); + final AlertDialog alertDialog = builder.create(); + + add.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + // TODO Auto-generated method stub + Thread addtoBookbag = new Thread(new Runnable() { + @Override + public void run() { + AccountAccess ac = AccountAccess + .getAccountAccess(); + try { + ac.addRecordToBookBag(info.doc_id, + bookBags.get(bookbag_selected).id); + } catch (SessionNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + runOnUiThread(new Runnable() { + @Override + public void run() { + progressDialog.dismiss(); + alertDialog.dismiss(); + } + }); + + } + }); + progressDialog = ProgressDialog.show(context, + getResources().getText(R.string.dialog_please_wait), + "Adding to bookbag"); + addtoBookbag.start(); + + } + }); + alertDialog.show(); + + s.setOnItemSelectedListener(new OnItemSelectedListener() { + + @Override + public void onItemSelected(AdapterView arg0, View arg1, + int position, long arg3) { + bookbag_selected = position; + } + + @Override + public void onNothingSelected(AdapterView arg0) { + } + + }); + } else + Toast.makeText(context, "No bookbags", Toast.LENGTH_SHORT) + .show(); + } + break; + } + + return super.onContextItemSelected(item); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + + switch (resultCode) { + + case SampleUnderlinesNoFade.RETURN_DATA : { + + ArrayList records = (ArrayList)data.getSerializableExtra("recordList"); + + recordList.clear(); + for(int i=0;i { + + private static final String tag = "SearchArrayAdapter"; + private Context context; + private ImageView recordImage; + private TextView recordTitle; + private TextView recordAuthor; + private TextView recordPublisher; + + private List records = new ArrayList(); + + public SearchArrayAdapter(Context context, int textViewResourceId, + List objects) { + super(context, textViewResourceId, objects); + this.context = context; + this.records = objects; + } + + public int getCount() { + return this.records.size(); + } + + public RecordInfo getItem(int index) { + return this.records.get(index); + } + + public View getView(int position, View convertView, ViewGroup parent) { + View row = convertView; + + // Get item + RecordInfo record = getItem(position); + + // if it is the right type of view + if (row == null + || row.findViewById(R.id.search_record_title) == null) { + + Log.d(tag, "Starting XML Row Inflation ... "); + LayoutInflater inflater = (LayoutInflater) this + .getContext().getSystemService( + Context.LAYOUT_INFLATER_SERVICE); + row = inflater.inflate(R.layout.search_result_item, parent, + false); + Log.d(tag, "Successfully completed XML Row Inflation!"); + + } + + Log.d(TAG, "reord image value " + recordImage); + // Get reference to ImageView + recordImage = (ImageView) row + .findViewById(R.id.search_record_img); + String imageHref = GlobalConfigs.httpAddress + + "/opac/extras/ac/jacket/small/" + record.isbn; + // start async download of image + imageDownloader.download(imageHref, recordImage); + // Get reference to TextView - title + recordTitle = (TextView) row + .findViewById(R.id.search_record_title); + + // Get reference to TextView - author + recordAuthor = (TextView) row + .findViewById(R.id.search_record_author); + + // Get referance to TextView - record Publisher date+publisher + recordPublisher = (TextView) row + .findViewById(R.id.search_record_publishing); + + // set text + recordTitle.setText(record.title); + recordAuthor.setText(record.author); + recordPublisher + .setText(record.pubdate + " " + record.publisher); + + return row; + } + } +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/services/NotificationAlert.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/services/NotificationAlert.java new file mode 100644 index 0000000000..73be455ac6 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/services/NotificationAlert.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.services; + +import java.util.Date; + +import org.androwrapee.db.DatabaseClass; +import org.androwrapee.db.DatabaseField; +import org.androwrapee.db.IdField; + +@DatabaseClass +public class NotificationAlert { + + public static final String tableName = "notifications"; + + public static final int NOTIFICATION_INTENT = 123456; + + @IdField + public long id; + + @DatabaseField + public int intent_val; + + @DatabaseField + public Date triggerDate; + + @DatabaseField + public String message; + + // required constructor for DAO + public NotificationAlert() { + + } + + public NotificationAlert(int id, int intent_val, Date triggerDate, + String message) { + + this.id = id; + this.intent_val = intent_val; + this.triggerDate = triggerDate; + this.message = message; + } + + @Override + public String toString() { + + return " Notification:[ id: " + id + "; intent_val: " + intent_val + + "; triggerDate : " + triggerDate + "; message: " + message + + "]"; + } +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/services/NotificationReceiver.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/services/NotificationReceiver.java new file mode 100644 index 0000000000..1904c2dcc4 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/services/NotificationReceiver.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.services; + +import org.evergreen_ils.views.splashscreen.SplashActivity; + +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; + +public class NotificationReceiver extends BroadcastReceiver { + + private final String TAG = NotificationReceiver.class.getName(); + public static final int NOTIFICATION_ID = 1; + + @Override + public void onReceive(Context context, Intent intent) { + + String ns = Context.NOTIFICATION_SERVICE; + NotificationManager mNotificationManager = (NotificationManager) context + .getSystemService(ns); + + String checkoutMessage = intent.getStringExtra("checkoutMesage"); + + Log.d(TAG, "Message " + checkoutMessage); + // send notification + + int icon = android.R.drawable.ic_dialog_alert; + CharSequence tickerText = "Checkout item due date"; + long when = System.currentTimeMillis(); + + Notification notification = new Notification(icon, tickerText, when); + + notification.defaults |= Notification.FLAG_AUTO_CANCEL; + + CharSequence contentTitle = "EG - checkout item due date"; + CharSequence contentText = checkoutMessage; + // start evergreen + Intent notificationIntent = new Intent(context, SplashActivity.class); + notificationIntent.putExtra("jump", "checkout_items"); + + PendingIntent contentIntent = PendingIntent.getActivity(context, 0, + notificationIntent, 0); + + notification.setLatestEventInfo(context, contentTitle, contentText, + contentIntent); + + mNotificationManager.notify(NOTIFICATION_ID, notification); + + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/services/PeriodicServiceBroadcastReceiver.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/services/PeriodicServiceBroadcastReceiver.java new file mode 100644 index 0000000000..f5a0cee48a --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/services/PeriodicServiceBroadcastReceiver.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.services; + +import java.util.Calendar; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.preference.PreferenceManager; +import android.util.Log; + +public class PeriodicServiceBroadcastReceiver extends BroadcastReceiver { + + public static final int INTENT_ID = 123; + + @Override + public void onReceive(Context context, Intent intent) { + + // do update logic + boolean mustDoUpdate = false; + + SharedPreferences prefs = PreferenceManager + .getDefaultSharedPreferences(context); + + // determine if to use alerts or not + boolean use_notifications = prefs.getBoolean("notifications_enabled", + false); + + if (use_notifications) { + // if no updates have been made + Calendar current = Calendar.getInstance(); + Calendar lastUpdateTime = Calendar.getInstance(); + lastUpdateTime.setTimeInMillis(prefs.getLong("lastUpdateTime", 0)); + + lastUpdateTime.add(Calendar.DAY_OF_MONTH, + ScheduledIntentService.SCHEDULE_TIME_INTERVAL); + + // if the last update time + elapsed scheduled time < current + // time we must do an update + if (lastUpdateTime.compareTo(current) == -1) { + mustDoUpdate = true; + } + + Log.d("app", "Network connectivity change or alarm must do update " + + mustDoUpdate); + + ConnectivityManager connMgr = (ConnectivityManager) context + .getSystemService(Context.CONNECTIVITY_SERVICE); + + NetworkInfo networkInfo = connMgr.getActiveNetworkInfo(); + // if internet available + if (networkInfo != null && networkInfo.isConnected()) { + + if (mustDoUpdate == true) { + Intent intentService = new Intent(context, + ScheduledIntentService.class); + context.startService(intentService); + } + } + + } + + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/services/RebootReceiver.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/services/RebootReceiver.java new file mode 100644 index 0000000000..e2ba90e962 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/services/RebootReceiver.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.services; + +import java.util.Calendar; + +import android.app.Activity; +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.widget.Toast; + +public class RebootReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent arg1) { + // reinitialize notifications + + SharedPreferences sharedPreferences = PreferenceManager + .getDefaultSharedPreferences(context); + + if (sharedPreferences.getBoolean("notifications_enabled", false)) { + + Toast.makeText(context, "Set up notification updates", + Toast.LENGTH_SHORT).show(); + // if enabled register the update service to run once per day + // get a Calendar object with current time + Calendar cal = Calendar.getInstance(); + + Intent bRecvIntent = new Intent(context, + PeriodicServiceBroadcastReceiver.class); + bRecvIntent.setAction(ScheduledIntentService.ACTION); + // update the current intent if it exists + PendingIntent sender = PendingIntent.getBroadcast(context, + NotificationAlert.NOTIFICATION_INTENT + + PeriodicServiceBroadcastReceiver.INTENT_ID, + bRecvIntent, PendingIntent.FLAG_UPDATE_CURRENT); + + // Get the AlarmManager service + AlarmManager am = (AlarmManager) context + .getSystemService(Activity.ALARM_SERVICE); + am.setRepeating(AlarmManager.RTC, cal.getTimeInMillis(), + 10000 * ScheduledIntentService.SCHEDULE_TIME_INTERVAL, + sender); + } + + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/services/ScheduledIntentService.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/services/ScheduledIntentService.java new file mode 100644 index 0000000000..a043b1a82e --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/services/ScheduledIntentService.java @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.services; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +import android.accounts.AccountManager; +import android.accounts.AccountManagerFuture; +import android.os.Bundle; +import org.androwrapee.db.DefaultDAO; +import org.evergreen_ils.accountAccess.AccountAccess; +import org.evergreen_ils.accountAccess.SessionNotFoundException; +import org.evergreen_ils.accountAccess.checkout.CircRecord; +import org.evergreen_ils.database.DatabaseManager; +import org.evergreen_ils.globals.GlobalConfigs; +import org.evergreen_ils.globals.Utils; +import org.evergreen_ils.auth.Const; +import org.open_ils.idl.IDLParser; + +import android.app.AlarmManager; +import android.app.IntentService; +import android.app.PendingIntent; +import android.content.Intent; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.util.Log; + +public class ScheduledIntentService extends IntentService { + + public static Date lastUpdateServiceDate; + + public static String TAG = ScheduledIntentService.class.getName(); + + public static String ACTION = "org.evergreen_ils.updateservice"; + + // fire up once a day + public static int SCHEDULE_TIME_INTERVAL = 1; + + public ScheduledIntentService() { + super("EvergreenIntentService"); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + Log.d(TAG, "Start service"); + + return super.onStartCommand(intent, flags, startId); + } + + //TODO: share some of this code with LoadingTask.doInBackground + //TODO: this code needs major work. I never saw it work so I don't + // feel bad about disabling it for now. + @Override + protected void onHandleIntent(Intent intent) { + + Date currentDate = new Date(System.currentTimeMillis()); + + Log.d(TAG, "Notifications service started"); + + /* + * Download the necessary IDL files for checkout items operations like + * au (for auth), circ, mvr and acp + */ + String idlFile = GlobalConfigs.IDL_FILE_FROM_ROOT + + "?class=circ&class=au&class=mvr&class=acp"; + try { + Log.d(TAG, "Load IDL start"); + InputStream in_IDL = Utils.getNetInputStream(GlobalConfigs.httpAddress + idlFile); + IDLParser parser = new IDLParser(in_IDL); + parser.setKeepIDLObjects(false); + parser.parse(); + } catch (Exception e) { + Log.w("Error in parsing IDL", e); + } + + /* + AccountAccess accountAccess = AccountAccess.getAccountAccess(GlobalConfigs.httpAddress); + Log.d(TAG, tag+"Signing in"); + AccountManager accountManager = AccountManager.get(this); + + // what needs to be done is + // 1. get last used account name + // 2. see if the account still exists + // 3. get an auth token for it + // 4. start an evergreen session + AccountManagerFuture future = accountManager.getAuthTokenByFeatures(Const.ACCOUNT_TYPE, Const.AUTHTOKEN_TYPE, null, mCallingActivity, null, null, null, null); + Bundle bnd = future.getResult(); + String auth_token = bnd.getString(AccountManager.KEY_AUTHTOKEN); + String account_name = bnd.getString(AccountManager.KEY_ACCOUNT_NAME); + Log.d(TAG, tag+"account_name="+account_name+" token="+auth_token); + + boolean auth = false; + if (auth) { + + SharedPreferences sharedPreferences = PreferenceManager + .getDefaultSharedPreferences(getApplicationContext()); + // int daysBeforeDueDate = + // sharedPreferences.getInt("notifications_days_before_expiration", + // 2); + // TODO + int daysBeforeDueDate = 2; + ArrayList circRecords = new ArrayList(); + + // get the circ records + try { + circRecords = accountAccess.getItemsCheckedOut(); + } catch (SessionNotFoundException e) { + // auth just earlier realized, not supose to happen + } + + DefaultDAO daoNotifications = DatabaseManager + .getDAOInstance(this, NotificationAlert.class, + NotificationAlert.tableName); + daoNotifications.open(); + + // Fetch all alarms from database + List alarms = daoNotifications.fetchAll(""); + + for (int i = 0; i < alarms.size(); i++) { + Log.d(TAG, "Notification " + alarms.get(i)); + } + for (int i = 0; i < circRecords.size(); i++) { + + CircRecord checkoutRecord = circRecords.get(i); + + Date dueDate = checkoutRecord.getDueDateObject(); + + Calendar notificationDate = Calendar.getInstance(); + notificationDate.setTime(dueDate); + + notificationDate.add(Calendar.DAY_OF_MONTH, -daysBeforeDueDate); + Log.d(TAG, + " notification time start " + + notificationDate.getTime() + " current date " + + currentDate + " date between " + currentDate); + + // if due date in the future + if (currentDate.compareTo(notificationDate.getTime()) >= 0) { + + // get a Calendar object with current time + Calendar cal = Calendar.getInstance(); + + cal.setTime(dueDate); + + // just for test + cal.add(Calendar.HOUR, 4); + cal.add(Calendar.MINUTE, 37); + + Log.d(TAG, "Set notification in " + cal.getTime()); + + NotificationAlert notifications = daoNotifications + .fetch(checkoutRecord.circ_id); + NotificationAlert newNotificationInf = new NotificationAlert( + checkoutRecord.circ_id, + NotificationAlert.NOTIFICATION_INTENT + + checkoutRecord.circ_id, cal.getTime(), + "Checkout " + checkoutRecord.getAuthor() + + " expires on " + + checkoutRecord.getDueDate()); + + if (notifications == null) { + daoNotifications.insert(newNotificationInf, false); + } else { + // update info in database + daoNotifications.update(newNotificationInf, + checkoutRecord.circ_id); + } + + Intent intentNotification = new Intent(this, + NotificationReceiver.class); + + Log.d(TAG, "Set due date alarm at" + cal.getTime() + + " for " + newNotificationInf.id + " intent_val: " + + newNotificationInf.intent_val); + + intentNotification.putExtra("checkoutMessage", + "The item " + checkoutRecord.getAuthor() + + " is about to expire on " + + checkoutRecord.getDueDate()); + // update the current intent if it exists + PendingIntent sender = PendingIntent.getBroadcast(this, + NotificationAlert.NOTIFICATION_INTENT + + checkoutRecord.circ_id, + intentNotification, + PendingIntent.FLAG_UPDATE_CURRENT); + + // Get the AlarmManager service + AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE); + am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), + sender); + } + } + daoNotifications.close(); + + lastUpdateServiceDate = currentDate; + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putLong("lastUpdateTime", lastUpdateServiceDate.getTime()); + editor.commit(); + + Log.d(TAG, "set last service update date " + lastUpdateServiceDate); + } + */ + } +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/utils/ui/BaseSampleActivity.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/utils/ui/BaseSampleActivity.java new file mode 100644 index 0000000000..46cb48de6a --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/utils/ui/BaseSampleActivity.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.utils.ui; + +import java.util.Random; + +import org.evergreen_ils.R; + +import android.support.v4.app.FragmentActivity; +import android.support.v4.view.ViewPager; +import android.view.Menu; +import android.view.MenuItem; +import android.widget.Toast; + +public abstract class BaseSampleActivity extends FragmentActivity { + private static final Random RANDOM = new Random(); + + public TestFragmentAdapter mAdapter; + public ViewPager mPager; + public PageIndicator mIndicator; + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.menu, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int i = item.getItemId(); + if (i == R.id.random) { + final int page = RANDOM.nextInt(mAdapter.getCount()); + Toast.makeText(this, "Changing to page " + page, Toast.LENGTH_SHORT); + mPager.setCurrentItem(page); + return true; + } else if (i == R.id.add_page) { + if (mAdapter.getCount() < 10) { + mIndicator.notifyDataSetChanged(); + } + return true; + } else if (i == R.id.remove_page) { + if (mAdapter.getCount() > 1) { + mIndicator.notifyDataSetChanged(); + } + return true; + } + return super.onOptionsItemSelected(item); + } +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/utils/ui/BasicDetailsFragment.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/utils/ui/BasicDetailsFragment.java new file mode 100644 index 0000000000..fb9175b18a --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/utils/ui/BasicDetailsFragment.java @@ -0,0 +1,393 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.utils.ui; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Map.Entry; +import java.util.Set; + +import android.util.Log; +import org.evergreen_ils.R; +import org.evergreen_ils.accountAccess.AccountAccess; +import org.evergreen_ils.accountAccess.SessionNotFoundException; +import org.evergreen_ils.accountAccess.bookbags.BookBag; +import org.evergreen_ils.accountAccess.holds.PlaceHold; +import org.evergreen_ils.globals.GlobalConfigs; +import org.evergreen_ils.searchCatalog.CopyInformation; +import org.evergreen_ils.searchCatalog.ImageDownloader; +import org.evergreen_ils.searchCatalog.MoreCopyInformation; +import org.evergreen_ils.searchCatalog.RecordInfo; +import org.evergreen_ils.searchCatalog.SearchCatalog; + +import android.app.Dialog; +import android.app.ProgressDialog; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemSelectedListener; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.Spinner; +import android.widget.TextView; +import android.widget.Toast; + +public class BasicDetailsFragment extends Fragment { + + private final String TAG = BasicDetailsFragment.class.getName(); + + private RecordInfo record; + private Integer position; + private Integer total; + + private TextView record_header; + + private TextView titleTextView; + private TextView authorTextView; + private TextView publisherTextView; + + private TextView seriesTextView; + private TextView subjectTextView; + private TextView synopsisTextView; + private TextView isbnTextView; + + private TextView copyCountTestView; + + private Button placeHoldButton; + + private Button addToBookbagButton; + + private LinearLayout showMore; + + private SearchCatalog search = null; + + private GlobalConfigs gl; + + private ProgressDialog progressDialog; + + private Integer bookbag_selected; + + private Dialog dialog; + + private ArrayList bookBags; + + private final ImageDownloader imageDownloader = new ImageDownloader(); + + private ImageView recordImage; + // max display info + private int list_size = 3; + + public static BasicDetailsFragment newInstance(RecordInfo record, + Integer position, Integer total) { + BasicDetailsFragment fragment = new BasicDetailsFragment(); + fragment.setDetails(record, position, total); + + return fragment; + } + + private void setDetails(RecordInfo record, Integer position, + Integer total) { + + this.record = record; + this.position = position; + this.total = total; + } + + public BasicDetailsFragment() { + + search = SearchCatalog.getInstance(); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (savedInstanceState != null) { + record = (RecordInfo) savedInstanceState + .getSerializable("recordInfo"); + this.position = savedInstanceState.getInt("position"); + this.total = savedInstanceState.getInt("total"); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + + gl = GlobalConfigs.getGlobalConfigs(getActivity()); + + LinearLayout layout = (LinearLayout) inflater.inflate( + R.layout.record_details_basic_fragment, null); + + record_header = (TextView) layout.findViewById(R.id.record_header_text); + copyCountTestView = (TextView) layout + .findViewById(R.id.record_details_simple_copy_count); + showMore = (LinearLayout) layout + .findViewById(R.id.record_details_show_more); + titleTextView = (TextView) layout + .findViewById(R.id.record_details_simple_title); + authorTextView = (TextView) layout + .findViewById(R.id.record_details_simple_author); + publisherTextView = (TextView) layout + .findViewById(R.id.record_details_simple_publisher); + + seriesTextView = (TextView) layout + .findViewById(R.id.record_details_simple_series); + subjectTextView = (TextView) layout + .findViewById(R.id.record_details_simple_subject); + synopsisTextView = (TextView) layout + .findViewById(R.id.record_details_simple_synopsis); + isbnTextView = (TextView) layout + .findViewById(R.id.record_details_simple_isbn); + + recordImage = (ImageView) layout + .findViewById(R.id.record_details_simple_image); + + placeHoldButton = (Button) layout + .findViewById(R.id.simple_place_hold_button); + addToBookbagButton = (Button) layout + .findViewById(R.id.simple_add_to_bookbag_button); + + placeHoldButton.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + Intent intent = new Intent(getActivity() + .getApplicationContext(), PlaceHold.class); + intent.putExtra("recordInfo", record); + startActivity(intent); + } + }); + + String imageHref = GlobalConfigs.httpAddress + + "/opac/extras/ac/jacket/large/" + record.isbn; + + // start async download of image + imageDownloader.download(imageHref, recordImage); + + AccountAccess ac = AccountAccess.getAccountAccess(); + + bookBags = ac.getBookbags(); + String array_spinner[] = new String[bookBags.size()]; + + for (int i = 0; i < array_spinner.length; i++) + array_spinner[i] = bookBags.get(i).name; + + dialog = new Dialog(getActivity()); + dialog.setContentView(R.layout.bookbag_spinner); + dialog.setTitle("Choose bookbag"); + Spinner s = (Spinner) dialog.findViewById(R.id.bookbag_spinner); + + Button add = (Button) dialog.findViewById(R.id.add_to_bookbag_button); + ArrayAdapter adapter = new ArrayAdapter(getActivity() + .getApplicationContext(), android.R.layout.simple_spinner_item, + array_spinner); + s.setAdapter(adapter); + + add.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + // TODO Auto-generated method stub + Thread addtoBookbag = new Thread(new Runnable() { + @Override + public void run() { + AccountAccess ac = AccountAccess.getAccountAccess(); + try { + ac.addRecordToBookBag(record.doc_id, + ac.getBookbags().get(bookbag_selected).id); + } catch (SessionNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + progressDialog.dismiss(); + dialog.dismiss(); + } + }); + + } + }); + progressDialog = ProgressDialog.show(getActivity(), + getResources().getText(R.string.dialog_please_wait), + "Adding to bookbag"); + addtoBookbag.start(); + + } + }); + s.setOnItemSelectedListener(new OnItemSelectedListener() { + + @Override + public void onItemSelected(AdapterView arg0, View arg1, + int position, long arg3) { + bookbag_selected = position; + } + + @Override + public void onNothingSelected(AdapterView arg0) { + } + + }); + + addToBookbagButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + + if (bookBags.size() > 0) + dialog.show(); + else + Toast.makeText(getActivity(), "No bookbags", + Toast.LENGTH_SHORT).show(); + } + + }); + } + }); + + record_header.setText(String.format(getString(R.string.record_of), position, total)); + + titleTextView.setText(record.title); + authorTextView.setText(record.author); + publisherTextView.setText(record.pubdate + " " + record.publisher); + + seriesTextView.setText(record.series); + subjectTextView.setText(record.subject); + synopsisTextView.setText(record.synopsis); + + isbnTextView.setText(record.isbn); + + int current_org = 0; + if (search != null) + current_org = search.selectedOrganization.id; + + Log.d(TAG, "Size " + record.copyCountListInfo.size()); + + for (int i = 0; i < record.copyCountListInfo.size(); i++) { + Log.d(TAG, current_org + " " + + record.copyCountListInfo.get(i).org_id + " " + + record.copyCountListInfo.get(i).count); + if (record.copyCountListInfo.get(i).org_id == current_org) { + int total = record.copyCountListInfo.get(i).count; + int available = record.copyCountListInfo.get(i).available; + copyCountTestView.setText(available + " / " + total); + break; + } + } + + final LayoutInflater inf = inflater; + final LinearLayout lay = layout; + + // add more details + showMore.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + // show more details + Intent intent = new Intent(getActivity() + .getApplicationContext(), MoreCopyInformation.class); + intent.putExtra("recordInfo", record); + startActivity(intent); + } + }); + + if (list_size > record.copyInformationList.size()) + list_size = record.copyInformationList.size(); + + // insert into main view + LinearLayout insertPoint = (LinearLayout) layout + .findViewById(R.id.record_details_copy_information); + addCopyInfo(0, list_size, inflater, insertPoint); + + return layout; + } + + @Override + public void onSaveInstanceState(Bundle outState) { + outState.putSerializable("recordInfo", record); + outState.putInt("position", this.position); + outState.putInt("total", this.total); + super.onSaveInstanceState(outState); + } + + public void addCopyInfo(int start, int stop, LayoutInflater inflater, + LinearLayout insertPoint) { + + for (int i = start; i < stop; i++) { + + View copy_info_view = inflater.inflate(R.layout.copy_information, + null); + + // fill in any details dynamically here + TextView library = (TextView) copy_info_view + .findViewById(R.id.copy_information_library); + TextView call_number = (TextView) copy_info_view + .findViewById(R.id.copy_information_call_number); + TextView copy_location = (TextView) copy_info_view + .findViewById(R.id.copy_information_copy_location); + + library.setText(gl.getOrganizationName(record.copyInformationList + .get(i).org_id) + " "); + call_number + .setText(record.copyInformationList.get(i).call_number_sufix); + copy_location + .setText(record.copyInformationList.get(i).copy_location); + + // insert into main view + insertPoint.addView(copy_info_view, new ViewGroup.LayoutParams( + LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT)); + + LinearLayout copy_statuses = (LinearLayout) copy_info_view + .findViewById(R.id.copy_information_statuses); + + CopyInformation info = record.copyInformationList.get(i); + + Set> set = info.statusInformation.entrySet(); + + Iterator> it = set.iterator(); + + while (it.hasNext()) { + + Entry ent = it.next(); + TextView statusName = new TextView(getActivity()); + statusName.setText(ent.getKey() + " : " + ent.getValue()); + + copy_statuses.addView(statusName, new LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); + + } + + } + + } +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/utils/ui/Dashboard.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/utils/ui/Dashboard.java new file mode 100644 index 0000000000..bbda569882 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/utils/ui/Dashboard.java @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.utils.ui; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; + +/** + * Custom layout that arranges children in a grid-like manner, optimizing for + * even horizontal and vertical whitespace. + */ +public class Dashboard extends ViewGroup { + + private static final int UNEVEN_GRID_PENALTY_MULTIPLIER = 10; + + private int mMaxChildWidth = 0; + private int mMaxChildHeight = 0; + + public Dashboard(Context context) { + super(context, null); + } + + public Dashboard(Context context, AttributeSet attrs) { + super(context, attrs, 0); + } + + public Dashboard(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + mMaxChildWidth = 0; + mMaxChildHeight = 0; + + // Measure once to find the maximum child size. + + int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec( + MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.AT_MOST); + int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec( + MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.AT_MOST); + + final int count = getChildCount(); + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child.getVisibility() == GONE) { + continue; + } + + child.measure(childWidthMeasureSpec, childHeightMeasureSpec); + + mMaxChildWidth = Math.max(mMaxChildWidth, child.getMeasuredWidth()); + mMaxChildHeight = Math.max(mMaxChildHeight, + child.getMeasuredHeight()); + } + + // Measure again for each child to be exactly the same size. + + childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(mMaxChildWidth, + MeasureSpec.EXACTLY); + childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(mMaxChildHeight, + MeasureSpec.EXACTLY); + + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child.getVisibility() == GONE) { + continue; + } + + child.measure(childWidthMeasureSpec, childHeightMeasureSpec); + } + + setMeasuredDimension(resolveSize(mMaxChildWidth, widthMeasureSpec), + resolveSize(mMaxChildHeight, heightMeasureSpec)); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + int width = r - l; + int height = b - t; + + final int count = getChildCount(); + + // Calculate the number of visible children. + int visibleCount = 0; + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child.getVisibility() == GONE) { + continue; + } + ++visibleCount; + } + + if (visibleCount == 0) { + return; + } + + // Calculate what number of rows and columns will optimize for even + // horizontal and + // vertical whitespace between items. Start with a 1 x N grid, then try + // 2 x N, and so on. + int bestSpaceDifference = Integer.MAX_VALUE; + int spaceDifference; + + // Horizontal and vertical space between items + int hSpace = 0; + int vSpace = 0; + + int cols = 1; + int rows; + + while (true) { + rows = (visibleCount - 1) / cols + 1; + + hSpace = ((width - mMaxChildWidth * cols) / (cols + 1)); + vSpace = ((height - mMaxChildHeight * rows) / (rows + 1)); + + spaceDifference = Math.abs(vSpace - hSpace); + if (rows * cols != visibleCount) { + spaceDifference *= UNEVEN_GRID_PENALTY_MULTIPLIER; + } + + if (spaceDifference < bestSpaceDifference) { + // Found a better whitespace squareness/ratio + bestSpaceDifference = spaceDifference; + + // If we found a better whitespace squareness and there's only 1 + // row, this is + // the best we can do. + if (rows == 1) { + break; + } + } else { + // This is a worse whitespace ratio, use the previous value of + // cols and exit. + --cols; + rows = (visibleCount - 1) / cols + 1; + hSpace = ((width - mMaxChildWidth * cols) / (cols + 1)); + vSpace = ((height - mMaxChildHeight * rows) / (rows + 1)); + break; + } + + ++cols; + } + + // Lay out children based on calculated best-fit number of rows and + // cols. + + // If we chose a layout that has negative horizontal or vertical space, + // force it to zero. + hSpace = Math.max(0, hSpace); + vSpace = Math.max(0, vSpace); + + // Re-use width/height variables to be child width/height. + width = (width - hSpace * (cols + 1)) / cols; + height = (height - vSpace * (rows + 1)) / rows; + + int left, top; + int col, row; + int visibleIndex = 0; + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child.getVisibility() == GONE) { + continue; + } + + row = visibleIndex / cols; + col = visibleIndex % cols; + + left = hSpace * (col + 1) + width * col; + top = vSpace * (row + 1) + height * row; + + child.layout(left, top, (hSpace == 0 && col == cols - 1) ? r + : (left + width), (vSpace == 0 && row == rows - 1) ? b + : (top + height)); + ++visibleIndex; + } + } +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/utils/ui/PageIndicator.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/utils/ui/PageIndicator.java new file mode 100644 index 0000000000..86aecd4c20 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/utils/ui/PageIndicator.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ + +package org.evergreen_ils.utils.ui; + +import android.support.v4.view.ViewPager; + +/** + * A PageIndicator is responsible to show an visual indicator on the total views + * number and the current visible view. + */ +public interface PageIndicator extends ViewPager.OnPageChangeListener { + /** + * Bind the indicator to a ViewPager. + * + * @param view + */ + void setViewPager(ViewPager view); + + /** + * Bind the indicator to a ViewPager. + * + * @param view + * @param initialPosition + */ + void setViewPager(ViewPager view, int initialPosition); + + /** + *

+ * Set the current page of both the ViewPager and indicator. + *

+ * + *

+ * This must be used if you need to set the page before the + * views are drawn on screen (e.g., default start page). + *

+ * + * @param item + */ + void setCurrentItem(int item); + + /** + * Set a page change listener which will receive forwarded events. + * + * @param listener + */ + void setOnPageChangeListener(ViewPager.OnPageChangeListener listener); + + /** + * Notify the indicator that the fragment list has changed. + */ + void notifyDataSetChanged(); +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/utils/ui/TabPageIndicator.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/utils/ui/TabPageIndicator.java new file mode 100644 index 0000000000..d5c1685f22 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/utils/ui/TabPageIndicator.java @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ + +package org.evergreen_ils.utils.ui; + +import static android.view.ViewGroup.LayoutParams; + +import org.evergreen_ils.R; + +import android.content.Context; +import android.support.v4.view.PagerAdapter; +import android.support.v4.view.ViewPager; +import android.support.v4.view.ViewPager.OnPageChangeListener; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.HorizontalScrollView; +import android.widget.LinearLayout; +import android.widget.TextView; + +/** + * This widget implements the dynamic action bar tab behavior that can change + * across different configurations or circumstances. + */ +public class TabPageIndicator extends HorizontalScrollView implements + PageIndicator { + /** Title text used when no title is provided by the adapter. */ + private static final CharSequence EMPTY_TITLE = ""; + + /** + * Interface for a callback when the selected tab has been reselected. + */ + public interface OnTabReselectedListener { + /** + * Callback when the selected tab has been reselected. + * + * @param position + * Position of the current center item. + */ + void onTabReselected(int position); + } + + private Runnable mTabSelector; + + private final OnClickListener mTabClickListener = new OnClickListener() { + public void onClick(View view) { + TabView tabView = (TabView) view; + final int oldSelected = mViewPager.getCurrentItem(); + final int newSelected = tabView.getIndex(); + mViewPager.setCurrentItem(newSelected); + if (oldSelected == newSelected && mTabReselectedListener != null) { + mTabReselectedListener.onTabReselected(newSelected); + } + } + }; + + private final LinearLayout mTabLayout; + private ViewPager mViewPager; + private ViewPager.OnPageChangeListener mListener; + + private int mMaxTabWidth; + private int mSelectedTabIndex; + + private OnTabReselectedListener mTabReselectedListener; + + public TabPageIndicator(Context context) { + this(context, null); + } + + public TabPageIndicator(Context context, AttributeSet attrs) { + super(context, attrs); + setHorizontalScrollBarEnabled(false); + + mTabLayout = new LinearLayout(getContext()); + addView(mTabLayout, new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT)); + } + + public void setOnTabReselectedListener(OnTabReselectedListener listener) { + mTabReselectedListener = listener; + } + + @Override + public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + final int widthMode = MeasureSpec.getMode(widthMeasureSpec); + final boolean lockedExpanded = widthMode == MeasureSpec.EXACTLY; + setFillViewport(lockedExpanded); + + final int childCount = mTabLayout.getChildCount(); + if (childCount > 1 + && (widthMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.AT_MOST)) { + if (childCount > 2) { + mMaxTabWidth = (int) (MeasureSpec.getSize(widthMeasureSpec) * 0.4f); + } else { + mMaxTabWidth = MeasureSpec.getSize(widthMeasureSpec) / 2; + } + } else { + mMaxTabWidth = -1; + } + + final int oldWidth = getMeasuredWidth(); + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + final int newWidth = getMeasuredWidth(); + + if (lockedExpanded && oldWidth != newWidth) { + // Recenter the tab display if we're at a new (scrollable) size. + setCurrentItem(mSelectedTabIndex); + } + } + + private void animateToTab(final int position) { + final View tabView = mTabLayout.getChildAt(position); + if (mTabSelector != null) { + removeCallbacks(mTabSelector); + } + mTabSelector = new Runnable() { + public void run() { + final int scrollPos = tabView.getLeft() + - (getWidth() - tabView.getWidth()) / 2; + smoothScrollTo(scrollPos, 0); + mTabSelector = null; + } + }; + post(mTabSelector); + } + + @Override + public void onAttachedToWindow() { + super.onAttachedToWindow(); + if (mTabSelector != null) { + // Re-post the selector we saved + post(mTabSelector); + } + } + + @Override + public void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (mTabSelector != null) { + removeCallbacks(mTabSelector); + } + } + + private void addTab(CharSequence text, int index) { + final TabView tabView = new TabView(getContext()); + tabView.mIndex = index; + tabView.setFocusable(true); + tabView.setOnClickListener(mTabClickListener); + tabView.setText(text); + + mTabLayout.addView(tabView, new LinearLayout.LayoutParams(0, + LayoutParams.MATCH_PARENT, 1)); + } + + @Override + public void onPageScrollStateChanged(int arg0) { + if (mListener != null) { + mListener.onPageScrollStateChanged(arg0); + } + } + + @Override + public void onPageScrolled(int arg0, float arg1, int arg2) { + if (mListener != null) { + mListener.onPageScrolled(arg0, arg1, arg2); + } + } + + @Override + public void onPageSelected(int arg0) { + setCurrentItem(arg0); + if (mListener != null) { + mListener.onPageSelected(arg0); + } + } + + @Override + public void setViewPager(ViewPager view) { + if (mViewPager == view) { + return; + } + if (mViewPager != null) { + mViewPager.setOnPageChangeListener(null); + } + final PagerAdapter adapter = view.getAdapter(); + if (adapter == null) { + throw new IllegalStateException( + "ViewPager does not have adapter instance."); + } + mViewPager = view; + view.setOnPageChangeListener(this); + notifyDataSetChanged(); + } + + public void notifyDataSetChanged() { + mTabLayout.removeAllViews(); + PagerAdapter adapter = mViewPager.getAdapter(); + final int count = adapter.getCount(); + for (int i = 0; i < count; i++) { + CharSequence title = adapter.getPageTitle(i); + if (title == null) { + title = EMPTY_TITLE; + } + addTab(title, i); + } + if (mSelectedTabIndex > count) { + mSelectedTabIndex = count - 1; + } + setCurrentItem(mSelectedTabIndex); + requestLayout(); + } + + @Override + public void setViewPager(ViewPager view, int initialPosition) { + setViewPager(view); + setCurrentItem(initialPosition); + } + + @Override + public void setCurrentItem(int item) { + if (mViewPager == null) { + throw new IllegalStateException("ViewPager has not been bound."); + } + mSelectedTabIndex = item; + mViewPager.setCurrentItem(item); + + final int tabCount = mTabLayout.getChildCount(); + for (int i = 0; i < tabCount; i++) { + final View child = mTabLayout.getChildAt(i); + final boolean isSelected = (i == item); + child.setSelected(isSelected); + if (isSelected) { + animateToTab(item); + } + } + } + + @Override + public void setOnPageChangeListener(OnPageChangeListener listener) { + mListener = listener; + } + + private class TabView extends TextView { + private int mIndex; + + public TabView(Context context) { + super(context, null, R.attr.vpiTabPageIndicatorStyle); + } + + @Override + public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + + // Re-measure if we went beyond our maximum size. + if (mMaxTabWidth > 0 && getMeasuredWidth() > mMaxTabWidth) { + super.onMeasure(MeasureSpec.makeMeasureSpec(mMaxTabWidth, + MeasureSpec.EXACTLY), heightMeasureSpec); + } + } + + public int getIndex() { + return mIndex; + } + } +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/utils/ui/TestFragment.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/utils/ui/TestFragment.java new file mode 100644 index 0000000000..36df8dde65 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/utils/ui/TestFragment.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.utils.ui; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.LinearLayout.LayoutParams; +import android.widget.TextView; + +public final class TestFragment extends Fragment { + private static final String KEY_CONTENT = "TestFragment:Content"; + + public static TestFragment newInstance(String content) { + TestFragment fragment = new TestFragment(); + + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < 20; i++) { + builder.append(content).append(" "); + } + builder.deleteCharAt(builder.length() - 1); + fragment.mContent = builder.toString(); + + return fragment; + } + + private String mContent = "???"; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + if ((savedInstanceState != null) + && savedInstanceState.containsKey(KEY_CONTENT)) { + mContent = savedInstanceState.getString(KEY_CONTENT); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + TextView text = new TextView(getActivity()); + text.setGravity(Gravity.CENTER); + text.setText(mContent); + text.setTextSize(20 * getResources().getDisplayMetrics().density); + text.setPadding(20, 20, 20, 20); + + LinearLayout layout = new LinearLayout(getActivity()); + layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, + LayoutParams.MATCH_PARENT)); + layout.setGravity(Gravity.CENTER); + layout.addView(text); + + return layout; + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putString(KEY_CONTENT, mContent); + } +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/utils/ui/TestFragmentAdapter.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/utils/ui/TestFragmentAdapter.java new file mode 100644 index 0000000000..120043b678 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/utils/ui/TestFragmentAdapter.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.utils.ui; + +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; + +public class TestFragmentAdapter extends FragmentPagerAdapter { + protected static final String[] CONTENT = new String[] { "This", "Is", "A", + "Test", }; + + private int mCount = CONTENT.length; + + public TestFragmentAdapter(FragmentManager fm) { + super(fm); + } + + @Override + public Fragment getItem(int position) { + return TestFragment.newInstance(CONTENT[position % CONTENT.length]); + } + + @Override + public int getCount() { + return mCount; + } + +} \ No newline at end of file diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/utils/ui/TitlePageIndicator.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/utils/ui/TitlePageIndicator.java new file mode 100644 index 0000000000..7b8de0e13d --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/utils/ui/TitlePageIndicator.java @@ -0,0 +1,881 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.utils.ui; + +import java.util.ArrayList; + +import org.evergreen_ils.R; + +import android.content.Context; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Rect; +import android.graphics.Typeface; +import android.os.Parcel; +import android.os.Parcelable; +import android.support.v4.view.MotionEventCompat; +import android.support.v4.view.PagerAdapter; +import android.support.v4.view.ViewConfigurationCompat; +import android.support.v4.view.ViewPager; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; + +/** + * A TitlePageIndicator is a PageIndicator which displays the title of left view + * (if exist), the title of the current select view (centered) and the title of + * the right view (if exist). When the user scrolls the ViewPager then titles + * are also scrolled. + */ +public class TitlePageIndicator extends View implements PageIndicator { + /** + * Percentage indicating what percentage of the screen width away from + * center should the underline be fully faded. A value of 0.25 means that + * halfway between the center of the screen and an edge. + */ + private static final float SELECTION_FADE_PERCENTAGE = 0.25f; + + /** + * Percentage indicating what percentage of the screen width away from + * center should the selected text bold turn off. A value of 0.05 means that + * 10% between the center and an edge. + */ + private static final float BOLD_FADE_PERCENTAGE = 0.05f; + + /** + * Title text used when no title is provided by the adapter. + */ + private static final String EMPTY_TITLE = ""; + + /** + * Interface for a callback when the center item has been clicked. + */ + public interface OnCenterItemClickListener { + /** + * Callback when the center item has been clicked. + * + * @param position + * Position of the current center item. + */ + void onCenterItemClick(int position); + } + + public enum IndicatorStyle { + None(0), Triangle(1), Underline(2); + + public final int value; + + private IndicatorStyle(int value) { + this.value = value; + } + + public static IndicatorStyle fromValue(int value) { + for (IndicatorStyle style : IndicatorStyle.values()) { + if (style.value == value) { + return style; + } + } + return null; + } + } + + private ViewPager mViewPager; + private ViewPager.OnPageChangeListener mListener; + private PagerAdapter mPagerAdapter; + private int mCurrentPage = -1; + private float mPageOffset; + private int mScrollState; + private final Paint mPaintText = new Paint(); + private boolean mBoldText; + private int mColorText; + private int mColorSelected; + private Path mPath = new Path(); + private final Rect mBounds = new Rect(); + private final Paint mPaintFooterLine = new Paint(); + private IndicatorStyle mFooterIndicatorStyle; + private final Paint mPaintFooterIndicator = new Paint(); + private float mFooterIndicatorHeight; + private float mFooterIndicatorUnderlinePadding; + private float mFooterPadding; + private float mTitlePadding; + private float mTopPadding; + /** Left and right side padding for not active view titles. */ + private float mClipPadding; + private float mFooterLineHeight; + + private static final int INVALID_POINTER = -1; + + private int mTouchSlop; + private float mLastMotionX = -1; + private int mActivePointerId = INVALID_POINTER; + private boolean mIsDragging; + + private OnCenterItemClickListener mCenterItemClickListener; + + public TitlePageIndicator(Context context) { + this(context, null); + } + + public TitlePageIndicator(Context context, AttributeSet attrs) { + this(context, attrs, R.attr.vpiTitlePageIndicatorStyle); + } + + public TitlePageIndicator(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + if (isInEditMode()) + return; + + // Load defaults from resources + final Resources res = getResources(); + final int defaultFooterColor = res + .getColor(R.color.default_title_indicator_footer_color); + final float defaultFooterLineHeight = res + .getDimension(R.dimen.default_title_indicator_footer_line_height); + final int defaultFooterIndicatorStyle = res + .getInteger(R.integer.default_title_indicator_footer_indicator_style); + final float defaultFooterIndicatorHeight = res + .getDimension(R.dimen.default_title_indicator_footer_indicator_height); + final float defaultFooterIndicatorUnderlinePadding = res + .getDimension(R.dimen.default_title_indicator_footer_indicator_underline_padding); + final float defaultFooterPadding = res + .getDimension(R.dimen.default_title_indicator_footer_padding); + final int defaultSelectedColor = res + .getColor(R.color.default_title_indicator_selected_color); + final boolean defaultSelectedBold = res + .getBoolean(R.bool.default_title_indicator_selected_bold); + final int defaultTextColor = res + .getColor(R.color.default_title_indicator_text_color); + final float defaultTextSize = res + .getDimension(R.dimen.default_title_indicator_text_size); + final float defaultTitlePadding = res + .getDimension(R.dimen.default_title_indicator_title_padding); + final float defaultClipPadding = res + .getDimension(R.dimen.default_title_indicator_clip_padding); + final float defaultTopPadding = res + .getDimension(R.dimen.default_title_indicator_top_padding); + + // Retrieve styles attributes + TypedArray a = context.obtainStyledAttributes(attrs, + R.styleable.TitlePageIndicator, defStyle, 0); + + // Retrieve the colors to be used for this view and apply them. + mFooterLineHeight = a.getDimension( + R.styleable.TitlePageIndicator_footerLineHeight, + defaultFooterLineHeight); + mFooterIndicatorStyle = IndicatorStyle.fromValue(a.getInteger( + R.styleable.TitlePageIndicator_footerIndicatorStyle, + defaultFooterIndicatorStyle)); + mFooterIndicatorHeight = a.getDimension( + R.styleable.TitlePageIndicator_footerIndicatorHeight, + defaultFooterIndicatorHeight); + mFooterIndicatorUnderlinePadding = a.getDimension( + R.styleable.TitlePageIndicator_footerIndicatorUnderlinePadding, + defaultFooterIndicatorUnderlinePadding); + mFooterPadding = a.getDimension( + R.styleable.TitlePageIndicator_footerPadding, + defaultFooterPadding); + mTopPadding = a.getDimension(R.styleable.TitlePageIndicator_topPadding, + defaultTopPadding); + mTitlePadding = a.getDimension( + R.styleable.TitlePageIndicator_titlePadding, + defaultTitlePadding); + mClipPadding = a.getDimension( + R.styleable.TitlePageIndicator_clipPadding, defaultClipPadding); + mColorSelected = a.getColor( + R.styleable.TitlePageIndicator_selectedColor, + defaultSelectedColor); + mColorText = a.getColor( + R.styleable.TitlePageIndicator_android_textColor, + defaultTextColor); + mBoldText = a.getBoolean(R.styleable.TitlePageIndicator_selectedBold, + defaultSelectedBold); + + final float textSize = a.getDimension( + R.styleable.TitlePageIndicator_android_textSize, + defaultTextSize); + final int footerColor = a.getColor( + R.styleable.TitlePageIndicator_footerColor, defaultFooterColor); + mPaintText.setTextSize(textSize); + mPaintText.setAntiAlias(true); + mPaintFooterLine.setStyle(Paint.Style.FILL_AND_STROKE); + mPaintFooterLine.setStrokeWidth(mFooterLineHeight); + mPaintFooterLine.setColor(footerColor); + mPaintFooterIndicator.setStyle(Paint.Style.FILL_AND_STROKE); + mPaintFooterIndicator.setColor(footerColor); + + a.recycle(); + + final ViewConfiguration configuration = ViewConfiguration.get(context); + mTouchSlop = ViewConfigurationCompat + .getScaledPagingTouchSlop(configuration); + } + + public int getFooterColor() { + return mPaintFooterLine.getColor(); + } + + public void setFooterColor(int footerColor) { + mPaintFooterLine.setColor(footerColor); + mPaintFooterIndicator.setColor(footerColor); + invalidate(); + } + + public float getFooterLineHeight() { + return mFooterLineHeight; + } + + public void setFooterLineHeight(float footerLineHeight) { + mFooterLineHeight = footerLineHeight; + mPaintFooterLine.setStrokeWidth(mFooterLineHeight); + invalidate(); + } + + public float getFooterIndicatorHeight() { + return mFooterIndicatorHeight; + } + + public void setFooterIndicatorHeight(float footerTriangleHeight) { + mFooterIndicatorHeight = footerTriangleHeight; + invalidate(); + } + + public float getFooterIndicatorPadding() { + return mFooterPadding; + } + + public void setFooterIndicatorPadding(float footerIndicatorPadding) { + mFooterPadding = footerIndicatorPadding; + invalidate(); + } + + public IndicatorStyle getFooterIndicatorStyle() { + return mFooterIndicatorStyle; + } + + public void setFooterIndicatorStyle(IndicatorStyle indicatorStyle) { + mFooterIndicatorStyle = indicatorStyle; + invalidate(); + } + + public int getSelectedColor() { + return mColorSelected; + } + + public void setSelectedColor(int selectedColor) { + mColorSelected = selectedColor; + invalidate(); + } + + public boolean isSelectedBold() { + return mBoldText; + } + + public void setSelectedBold(boolean selectedBold) { + mBoldText = selectedBold; + invalidate(); + } + + public int getTextColor() { + return mColorText; + } + + public void setTextColor(int textColor) { + mPaintText.setColor(textColor); + mColorText = textColor; + invalidate(); + } + + public float getTextSize() { + return mPaintText.getTextSize(); + } + + public void setTextSize(float textSize) { + mPaintText.setTextSize(textSize); + invalidate(); + } + + public float getTitlePadding() { + return this.mTitlePadding; + } + + public void setTitlePadding(float titlePadding) { + mTitlePadding = titlePadding; + invalidate(); + } + + public float getTopPadding() { + return this.mTopPadding; + } + + public void setTopPadding(float topPadding) { + mTopPadding = topPadding; + invalidate(); + } + + public float getClipPadding() { + return this.mClipPadding; + } + + public void setClipPadding(float clipPadding) { + mClipPadding = clipPadding; + invalidate(); + } + + public void setTypeface(Typeface typeface) { + mPaintText.setTypeface(typeface); + invalidate(); + } + + public Typeface getTypeface() { + return mPaintText.getTypeface(); + } + + /* + * (non-Javadoc) + * + * @see android.view.View#onDraw(android.graphics.Canvas) + */ + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + if (mViewPager == null) { + return; + } + final int count = mViewPager.getAdapter().getCount(); + if (count == 0) { + return; + } + + // mCurrentPage is -1 on first start and after orientation changed. If + // so, retrieve the correct index from viewpager. + if (mCurrentPage == -1 && mViewPager != null) + mCurrentPage = mViewPager.getCurrentItem(); + + // Calculate views bounds + ArrayList bounds = calculateAllBounds(mPaintText); + final int boundsSize = bounds.size(); + + // Make sure we're on a page that still exists + if (mCurrentPage >= boundsSize) { + setCurrentItem(boundsSize - 1); + return; + } + + final int countMinusOne = count - 1; + final float halfWidth = getWidth() / 2f; + final int left = getLeft(); + final float leftClip = left + mClipPadding; + final int width = getWidth(); + final int height = getHeight(); + final int right = left + width; + final float rightClip = right - mClipPadding; + + int page = mCurrentPage; + float offsetPercent; + if (mPageOffset <= 0.5) { + offsetPercent = mPageOffset; + } else { + page += 1; + offsetPercent = 1 - mPageOffset; + } + final boolean currentSelected = (offsetPercent <= SELECTION_FADE_PERCENTAGE); + final boolean currentBold = (offsetPercent <= BOLD_FADE_PERCENTAGE); + final float selectedPercent = (SELECTION_FADE_PERCENTAGE - offsetPercent) + / SELECTION_FADE_PERCENTAGE; + + // Verify if the current view must be clipped to the screen + Rect curPageBound = bounds.get(mCurrentPage); + float curPageWidth = curPageBound.right - curPageBound.left; + if (curPageBound.left < leftClip) { + // Try to clip to the screen (left side) + clipViewOnTheLeft(curPageBound, curPageWidth, left); + } + if (curPageBound.right > rightClip) { + // Try to clip to the screen (right side) + clipViewOnTheRight(curPageBound, curPageWidth, right); + } + + // Left views starting from the current position + if (mCurrentPage > 0) { + for (int i = mCurrentPage - 1; i >= 0; i--) { + Rect bound = bounds.get(i); + // Is left side is outside the screen + if (bound.left < leftClip) { + int w = bound.right - bound.left; + // Try to clip to the screen (left side) + clipViewOnTheLeft(bound, w, left); + // Except if there's an intersection with the right view + Rect rightBound = bounds.get(i + 1); + // Intersection + if (bound.right + mTitlePadding > rightBound.left) { + bound.left = (int) (rightBound.left - w - mTitlePadding); + bound.right = bound.left + w; + } + } + } + } + // Right views starting from the current position + if (mCurrentPage < countMinusOne) { + for (int i = mCurrentPage + 1; i < count; i++) { + Rect bound = bounds.get(i); + // If right side is outside the screen + if (bound.right > rightClip) { + int w = bound.right - bound.left; + // Try to clip to the screen (right side) + clipViewOnTheRight(bound, w, right); + // Except if there's an intersection with the left view + Rect leftBound = bounds.get(i - 1); + // Intersection + if (bound.left - mTitlePadding < leftBound.right) { + bound.left = (int) (leftBound.right + mTitlePadding); + bound.right = bound.left + w; + } + } + } + } + + // Now draw views + int colorTextAlpha = mColorText >>> 24; + for (int i = 0; i < count; i++) { + // Get the title + Rect bound = bounds.get(i); + // Only if one side is visible + if ((bound.left > left && bound.left < right) + || (bound.right > left && bound.right < right)) { + final boolean currentPage = (i == page); + final CharSequence pageTitle = getTitle(i); + + // Only set bold if we are within bounds + mPaintText.setFakeBoldText(currentPage && currentBold + && mBoldText); + + // Draw text as unselected + mPaintText.setColor(mColorText); + if (currentPage && currentSelected) { + // Fade out/in unselected text as the selected text fades + // in/out + mPaintText.setAlpha(colorTextAlpha + - (int) (colorTextAlpha * selectedPercent)); + } + canvas.drawText(pageTitle, 0, pageTitle.length(), bound.left, + bound.bottom + mTopPadding, mPaintText); + + // If we are within the selected bounds draw the selected text + if (currentPage && currentSelected) { + mPaintText.setColor(mColorSelected); + mPaintText + .setAlpha((int) ((mColorSelected >>> 24) * selectedPercent)); + canvas.drawText(pageTitle, 0, pageTitle.length(), + bound.left, bound.bottom + mTopPadding, mPaintText); + } + } + } + + // Draw the footer line + mPath.reset(); + mPath.moveTo(0, height - mFooterLineHeight / 2f); + mPath.lineTo(width, height - mFooterLineHeight / 2f); + mPath.close(); + canvas.drawPath(mPath, mPaintFooterLine); + + switch (mFooterIndicatorStyle) { + case Triangle: + mPath.reset(); + mPath.moveTo(halfWidth, height - mFooterLineHeight + - mFooterIndicatorHeight); + mPath.lineTo(halfWidth + mFooterIndicatorHeight, height + - mFooterLineHeight); + mPath.lineTo(halfWidth - mFooterIndicatorHeight, height + - mFooterLineHeight); + mPath.close(); + canvas.drawPath(mPath, mPaintFooterIndicator); + break; + + case Underline: + if (!currentSelected || page >= boundsSize) { + break; + } + + Rect underlineBounds = bounds.get(page); + mPath.reset(); + mPath.moveTo(underlineBounds.left + - mFooterIndicatorUnderlinePadding, height + - mFooterLineHeight); + mPath.lineTo(underlineBounds.right + + mFooterIndicatorUnderlinePadding, height + - mFooterLineHeight); + mPath.lineTo(underlineBounds.right + + mFooterIndicatorUnderlinePadding, height + - mFooterLineHeight - mFooterIndicatorHeight); + mPath.lineTo(underlineBounds.left + - mFooterIndicatorUnderlinePadding, height + - mFooterLineHeight - mFooterIndicatorHeight); + mPath.close(); + + mPaintFooterIndicator.setAlpha((int) (0xFF * selectedPercent)); + canvas.drawPath(mPath, mPaintFooterIndicator); + mPaintFooterIndicator.setAlpha(0xFF); + break; + } + } + + public boolean onTouchEvent(android.view.MotionEvent ev) { + if (super.onTouchEvent(ev)) { + return true; + } + if ((mViewPager == null) || (mViewPager.getAdapter().getCount() == 0)) { + return false; + } + + final int action = ev.getAction(); + + switch (action & MotionEventCompat.ACTION_MASK) { + case MotionEvent.ACTION_DOWN: + mActivePointerId = MotionEventCompat.getPointerId(ev, 0); + mLastMotionX = ev.getX(); + break; + + case MotionEvent.ACTION_MOVE: { + final int activePointerIndex = MotionEventCompat.findPointerIndex( + ev, mActivePointerId); + final float x = MotionEventCompat.getX(ev, activePointerIndex); + final float deltaX = x - mLastMotionX; + + if (!mIsDragging) { + if (Math.abs(deltaX) > mTouchSlop) { + mIsDragging = true; + } + } + + if (mIsDragging) { + mLastMotionX = x; + if (mViewPager.isFakeDragging() || mViewPager.beginFakeDrag()) { + mViewPager.fakeDragBy(deltaX); + } + } + + break; + } + + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + if (!mIsDragging) { + final int count = mViewPager.getAdapter().getCount(); + final int width = getWidth(); + final float halfWidth = width / 2f; + final float sixthWidth = width / 6f; + final float leftThird = halfWidth - sixthWidth; + final float rightThird = halfWidth + sixthWidth; + final float eventX = ev.getX(); + + if (eventX < leftThird) { + if (mCurrentPage > 0) { + mViewPager.setCurrentItem(mCurrentPage - 1); + return true; + } + } else if (eventX > rightThird) { + if (mCurrentPage < count - 1) { + mViewPager.setCurrentItem(mCurrentPage + 1); + return true; + } + } else { + // Middle third + if (mCenterItemClickListener != null) { + mCenterItemClickListener + .onCenterItemClick(mCurrentPage); + } + } + } + + mIsDragging = false; + mActivePointerId = INVALID_POINTER; + if (mViewPager.isFakeDragging()) + mViewPager.endFakeDrag(); + break; + + case MotionEventCompat.ACTION_POINTER_DOWN: { + final int index = MotionEventCompat.getActionIndex(ev); + final float x = MotionEventCompat.getX(ev, index); + mLastMotionX = x; + mActivePointerId = MotionEventCompat.getPointerId(ev, index); + break; + } + + case MotionEventCompat.ACTION_POINTER_UP: + final int pointerIndex = MotionEventCompat.getActionIndex(ev); + final int pointerId = MotionEventCompat.getPointerId(ev, + pointerIndex); + if (pointerId == mActivePointerId) { + final int newPointerIndex = pointerIndex == 0 ? 1 : 0; + mActivePointerId = MotionEventCompat.getPointerId(ev, + newPointerIndex); + } + mLastMotionX = MotionEventCompat.getX(ev, + MotionEventCompat.findPointerIndex(ev, mActivePointerId)); + break; + } + + return true; + }; + + /** + * Set bounds for the right textView including clip padding. + * + * @param curViewBound + * current bounds. + * @param curViewWidth + * width of the view. + */ + private void clipViewOnTheRight(Rect curViewBound, float curViewWidth, + int right) { + curViewBound.right = (int) (right - mClipPadding); + curViewBound.left = (int) (curViewBound.right - curViewWidth); + } + + /** + * Set bounds for the left textView including clip padding. + * + * @param curViewBound + * current bounds. + * @param curViewWidth + * width of the view. + */ + private void clipViewOnTheLeft(Rect curViewBound, float curViewWidth, + int left) { + curViewBound.left = (int) (left + mClipPadding); + curViewBound.right = (int) (mClipPadding + curViewWidth); + } + + /** + * Calculate views bounds and scroll them according to the current index + * + * @param paint + * @return + */ + private ArrayList calculateAllBounds(Paint paint) { + ArrayList list = new ArrayList(); + // For each views (If no values then add a fake one) + final int count = mViewPager.getAdapter().getCount(); + final int width = getWidth(); + final int halfWidth = width / 2; + for (int i = 0; i < count; i++) { + Rect bounds = calcBounds(i, paint); + int w = bounds.right - bounds.left; + int h = bounds.bottom - bounds.top; + bounds.left = (int) (halfWidth - (w / 2f) + ((i - mCurrentPage - mPageOffset) * width)); + bounds.right = bounds.left + w; + bounds.top = 0; + bounds.bottom = h; + list.add(bounds); + } + + return list; + } + + /** + * Calculate the bounds for a view's title + * + * @param index + * @param paint + * @return + */ + private Rect calcBounds(int index, Paint paint) { + // Calculate the text bounds + Rect bounds = new Rect(); + CharSequence title = getTitle(index); + bounds.right = (int) paint.measureText(title, 0, title.length()); + bounds.bottom = (int) (paint.descent() - paint.ascent()); + return bounds; + } + + @Override + public void setViewPager(ViewPager view) { + if (mViewPager == view) { + return; + } + if (mViewPager != null) { + mViewPager.setOnPageChangeListener(null); + } + mPagerAdapter = view.getAdapter(); + if (mPagerAdapter == null) { + throw new IllegalStateException( + "ViewPager does not have adapter instance."); + } + mViewPager = view; + mViewPager.setOnPageChangeListener(this); + invalidate(); + } + + @Override + public void setViewPager(ViewPager view, int initialPosition) { + setViewPager(view); + setCurrentItem(initialPosition); + } + + @Override + public void notifyDataSetChanged() { + invalidate(); + } + + /** + * Set a callback listener for the center item click. + * + * @param listener + * Callback instance. + */ + public void setOnCenterItemClickListener(OnCenterItemClickListener listener) { + mCenterItemClickListener = listener; + } + + @Override + public void setCurrentItem(int item) { + if (mViewPager == null) { + throw new IllegalStateException("ViewPager has not been bound."); + } + mViewPager.setCurrentItem(item); + mCurrentPage = item; + invalidate(); + } + + @Override + public void onPageScrollStateChanged(int state) { + mScrollState = state; + + if (mListener != null) { + mListener.onPageScrollStateChanged(state); + } + } + + @Override + public void onPageScrolled(int position, float positionOffset, + int positionOffsetPixels) { + mCurrentPage = position; + mPageOffset = positionOffset; + invalidate(); + + if (mListener != null) { + mListener.onPageScrolled(position, positionOffset, + positionOffsetPixels); + } + } + + @Override + public void onPageSelected(int position) { + if (mScrollState == ViewPager.SCROLL_STATE_IDLE) { + mCurrentPage = position; + invalidate(); + } + + if (mListener != null) { + mListener.onPageSelected(position); + } + } + + @Override + public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) { + mListener = listener; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // Measure our width in whatever mode specified + final int measuredWidth = MeasureSpec.getSize(widthMeasureSpec); + + // Determine our height + float height = 0; + final int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec); + if (heightSpecMode == MeasureSpec.EXACTLY) { + // We were told how big to be + height = MeasureSpec.getSize(heightMeasureSpec); + } else { + // Calculate the text bounds + mBounds.setEmpty(); + mBounds.bottom = (int) (mPaintText.descent() - mPaintText.ascent()); + height = mBounds.bottom - mBounds.top + mFooterLineHeight + + mFooterPadding + mTopPadding; + if (mFooterIndicatorStyle != IndicatorStyle.None) { + height += mFooterIndicatorHeight; + } + } + final int measuredHeight = (int) height; + + setMeasuredDimension(measuredWidth, measuredHeight); + } + + @Override + public void onRestoreInstanceState(Parcelable state) { + SavedState savedState = (SavedState) state; + super.onRestoreInstanceState(savedState.getSuperState()); + mCurrentPage = savedState.currentPage; + requestLayout(); + } + + @Override + public Parcelable onSaveInstanceState() { + Parcelable superState = super.onSaveInstanceState(); + SavedState savedState = new SavedState(superState); + savedState.currentPage = mCurrentPage; + return savedState; + } + + static class SavedState extends BaseSavedState { + int currentPage; + + public SavedState(Parcelable superState) { + super(superState); + } + + private SavedState(Parcel in) { + super(in); + currentPage = in.readInt(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeInt(currentPage); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + @Override + public SavedState createFromParcel(Parcel in) { + return new SavedState(in); + } + + @Override + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; + } + + private CharSequence getTitle(int i) { + CharSequence title = mPagerAdapter.getPageTitle(i); + if (title == null) { + title = EMPTY_TITLE; + } + return title.toString(); + } +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/utils/ui/UnderlinePageIndicator.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/utils/ui/UnderlinePageIndicator.java new file mode 100644 index 0000000000..e692437cdd --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/utils/ui/UnderlinePageIndicator.java @@ -0,0 +1,424 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.utils.ui; + +import org.evergreen_ils.R; + +import android.content.Context; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.os.Parcel; +import android.os.Parcelable; +import android.support.v4.view.MotionEventCompat; +import android.support.v4.view.ViewConfigurationCompat; +import android.support.v4.view.ViewPager; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; + +/** + * Draws a line for each page. The current page line is colored differently than + * the unselected page lines. + */ +public class UnderlinePageIndicator extends View implements PageIndicator { + private static final int INVALID_POINTER = -1; + private static final int FADE_FRAME_MS = 30; + + private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + + private boolean mFades; + private int mFadeDelay; + private int mFadeLength; + private int mFadeBy; + + private ViewPager mViewPager; + private ViewPager.OnPageChangeListener mListener; + private int mScrollState; + private int mCurrentPage; + private float mPositionOffset; + + private int mTouchSlop; + private float mLastMotionX = -1; + private int mActivePointerId = INVALID_POINTER; + private boolean mIsDragging; + + private final Runnable mFadeRunnable = new Runnable() { + @Override + public void run() { + final int alpha = Math.max(mPaint.getAlpha() - mFadeBy, 0); + mPaint.setAlpha(alpha); + invalidate(); + if (alpha > 0) { + postDelayed(this, FADE_FRAME_MS); + } + } + }; + + public UnderlinePageIndicator(Context context) { + this(context, null); + } + + public UnderlinePageIndicator(Context context, AttributeSet attrs) { + this(context, attrs, R.attr.vpiUnderlinePageIndicatorStyle); + } + + public UnderlinePageIndicator(Context context, AttributeSet attrs, + int defStyle) { + super(context, attrs, defStyle); + if (isInEditMode()) + return; + + final Resources res = getResources(); + + // Load defaults from resources + final boolean defaultFades = res + .getBoolean(R.bool.default_underline_indicator_fades); + final int defaultFadeDelay = res + .getInteger(R.integer.default_underline_indicator_fade_delay); + final int defaultFadeLength = res + .getInteger(R.integer.default_underline_indicator_fade_length); + final int defaultSelectedColor = res + .getColor(R.color.default_underline_indicator_selected_color); + + // Retrieve styles attributes + TypedArray a = context.obtainStyledAttributes(attrs, + R.styleable.UnderlinePageIndicator, defStyle, 0); + + setFades(a.getBoolean(R.styleable.UnderlinePageIndicator_fades, + defaultFades)); + setSelectedColor(a.getColor( + R.styleable.UnderlinePageIndicator_selectedColor, + defaultSelectedColor)); + setFadeDelay(a.getInteger(R.styleable.UnderlinePageIndicator_fadeDelay, + defaultFadeDelay)); + setFadeLength(a.getInteger( + R.styleable.UnderlinePageIndicator_fadeLength, + defaultFadeLength)); + + a.recycle(); + + final ViewConfiguration configuration = ViewConfiguration.get(context); + mTouchSlop = ViewConfigurationCompat + .getScaledPagingTouchSlop(configuration); + } + + public boolean getFades() { + return mFades; + } + + public void setFades(boolean fades) { + if (fades != mFades) { + mFades = fades; + if (fades) { + post(mFadeRunnable); + } else { + removeCallbacks(mFadeRunnable); + mPaint.setAlpha(0xFF); + invalidate(); + } + } + } + + public int getFadeDelay() { + return mFadeDelay; + } + + public void setFadeDelay(int fadeDelay) { + mFadeDelay = fadeDelay; + } + + public int getFadeLength() { + return mFadeLength; + } + + public void setFadeLength(int fadeLength) { + mFadeLength = fadeLength; + mFadeBy = 0xFF / (mFadeLength / FADE_FRAME_MS); + } + + public int getSelectedColor() { + return mPaint.getColor(); + } + + public void setSelectedColor(int selectedColor) { + mPaint.setColor(selectedColor); + invalidate(); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + if (mViewPager == null) { + return; + } + final int count = mViewPager.getAdapter().getCount(); + if (count == 0) { + return; + } + + if (mCurrentPage >= count) { + setCurrentItem(count - 1); + return; + } + + final int paddingLeft = getPaddingLeft(); + final float pageWidth = (getWidth() - paddingLeft - getPaddingRight()) + / (1f * count); + final float left = paddingLeft + pageWidth + * (mCurrentPage + mPositionOffset); + final float right = left + pageWidth; + final float top = getPaddingTop(); + final float bottom = getHeight() - getPaddingBottom(); + canvas.drawRect(left, top, right, bottom, mPaint); + } + + public boolean onTouchEvent(MotionEvent ev) { + if (super.onTouchEvent(ev)) { + return true; + } + if ((mViewPager == null) || (mViewPager.getAdapter().getCount() == 0)) { + return false; + } + + final int action = ev.getAction(); + + switch (action & MotionEventCompat.ACTION_MASK) { + case MotionEvent.ACTION_DOWN: + mActivePointerId = MotionEventCompat.getPointerId(ev, 0); + mLastMotionX = ev.getX(); + break; + + case MotionEvent.ACTION_MOVE: { + final int activePointerIndex = MotionEventCompat.findPointerIndex( + ev, mActivePointerId); + final float x = MotionEventCompat.getX(ev, activePointerIndex); + final float deltaX = x - mLastMotionX; + + if (!mIsDragging) { + if (Math.abs(deltaX) > mTouchSlop) { + mIsDragging = true; + } + } + + if (mIsDragging) { + mLastMotionX = x; + if (mViewPager.isFakeDragging() || mViewPager.beginFakeDrag()) { + mViewPager.fakeDragBy(deltaX); + } + } + + break; + } + + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + if (!mIsDragging) { + final int count = mViewPager.getAdapter().getCount(); + final int width = getWidth(); + final float halfWidth = width / 2f; + final float sixthWidth = width / 6f; + + if ((mCurrentPage > 0) && (ev.getX() < halfWidth - sixthWidth)) { + mViewPager.setCurrentItem(mCurrentPage - 1); + return true; + } else if ((mCurrentPage < count - 1) + && (ev.getX() > halfWidth + sixthWidth)) { + mViewPager.setCurrentItem(mCurrentPage + 1); + return true; + } + } + + mIsDragging = false; + mActivePointerId = INVALID_POINTER; + if (mViewPager.isFakeDragging()) + mViewPager.endFakeDrag(); + break; + + case MotionEventCompat.ACTION_POINTER_DOWN: { + final int index = MotionEventCompat.getActionIndex(ev); + final float x = MotionEventCompat.getX(ev, index); + mLastMotionX = x; + mActivePointerId = MotionEventCompat.getPointerId(ev, index); + break; + } + + case MotionEventCompat.ACTION_POINTER_UP: + final int pointerIndex = MotionEventCompat.getActionIndex(ev); + final int pointerId = MotionEventCompat.getPointerId(ev, + pointerIndex); + if (pointerId == mActivePointerId) { + final int newPointerIndex = pointerIndex == 0 ? 1 : 0; + mActivePointerId = MotionEventCompat.getPointerId(ev, + newPointerIndex); + } + mLastMotionX = MotionEventCompat.getX(ev, + MotionEventCompat.findPointerIndex(ev, mActivePointerId)); + break; + } + + return true; + }; + + @Override + public void setViewPager(ViewPager viewPager) { + if (mViewPager == viewPager) { + return; + } + if (mViewPager != null) { + // Clear us from the old pager. + mViewPager.setOnPageChangeListener(null); + } + if (viewPager.getAdapter() == null) { + throw new IllegalStateException( + "ViewPager does not have adapter instance."); + } + mViewPager = viewPager; + mViewPager.setOnPageChangeListener(this); + invalidate(); + post(new Runnable() { + @Override + public void run() { + if (mFades) { + post(mFadeRunnable); + } + } + }); + } + + @Override + public void setViewPager(ViewPager view, int initialPosition) { + setViewPager(view); + setCurrentItem(initialPosition); + } + + @Override + public void setCurrentItem(int item) { + if (mViewPager == null) { + throw new IllegalStateException("ViewPager has not been bound."); + } + mViewPager.setCurrentItem(item); + mCurrentPage = item; + invalidate(); + } + + @Override + public void notifyDataSetChanged() { + invalidate(); + } + + @Override + public void onPageScrollStateChanged(int state) { + mScrollState = state; + + if (mListener != null) { + mListener.onPageScrollStateChanged(state); + } + } + + @Override + public void onPageScrolled(int position, float positionOffset, + int positionOffsetPixels) { + mCurrentPage = position; + mPositionOffset = positionOffset; + if (mFades) { + if (positionOffsetPixels > 0) { + removeCallbacks(mFadeRunnable); + mPaint.setAlpha(0xFF); + } else if (mScrollState != ViewPager.SCROLL_STATE_DRAGGING) { + postDelayed(mFadeRunnable, mFadeDelay); + } + } + invalidate(); + + if (mListener != null) { + mListener.onPageScrolled(position, positionOffset, + positionOffsetPixels); + } + } + + @Override + public void onPageSelected(int position) { + if (mScrollState == ViewPager.SCROLL_STATE_IDLE) { + mCurrentPage = position; + mPositionOffset = 0; + invalidate(); + mFadeRunnable.run(); + } + if (mListener != null) { + mListener.onPageSelected(position); + } + } + + @Override + public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) { + mListener = listener; + } + + @Override + public void onRestoreInstanceState(Parcelable state) { + SavedState savedState = (SavedState) state; + super.onRestoreInstanceState(savedState.getSuperState()); + mCurrentPage = savedState.currentPage; + requestLayout(); + } + + @Override + public Parcelable onSaveInstanceState() { + Parcelable superState = super.onSaveInstanceState(); + SavedState savedState = new SavedState(superState); + savedState.currentPage = mCurrentPage; + return savedState; + } + + static class SavedState extends BaseSavedState { + int currentPage; + + public SavedState(Parcelable superState) { + super(superState); + } + + private SavedState(Parcel in) { + super(in); + currentPage = in.readInt(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeInt(currentPage); + } + + public static final Creator CREATOR = new Creator() { + @Override + public SavedState createFromParcel(Parcel in) { + return new SavedState(in); + } + + @Override + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; + } +} \ No newline at end of file diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/views/AccountScreenDashboard.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/views/AccountScreenDashboard.java new file mode 100644 index 0000000000..e55b42d518 --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/views/AccountScreenDashboard.java @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.views; + +import org.evergreen_ils.R; +import org.evergreen_ils.accountAccess.bookbags.BookbagsListView; +import org.evergreen_ils.accountAccess.checkout.ItemsCheckOutListView; +import org.evergreen_ils.accountAccess.fines.FinesActivity; +import org.evergreen_ils.accountAccess.holds.HoldsListView; +import org.evergreen_ils.searchCatalog.SearchCatalogListView; +import org.evergreen_ils.views.splashscreen.SplashActivity; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; + +public class AccountScreenDashboard extends Activity { + + /** + * onCreate - called when the activity is first created. + * + * Called when the activity is first created. This is where you should do + * all of your normal static set up: create views, bind data to lists, etc. + * This method also provides you with a Bundle containing the activity's + * previously frozen state, if there was one. + * + * Always followed by onStart(). + * + */ + + private Button homeButton = null; + + private Button myAccountButton = null; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (!SplashActivity.isAppInitialized()) { + SplashActivity.restartApp(this); + return; + } + + setContentView(R.layout.dashbord_account); + +// myAccountButton = (Button) findViewById(R.id.my_account_button); +// myAccountButton.setEnabled(false); +// myAccountButton.setOnClickListener(new OnClickListener() { +// @Override +// public void onClick(View v) { +// } +// }); + + homeButton = (Button) findViewById(R.id.action_bar_home_button); + homeButton.setText(R.string.my_account_button_text); + homeButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + + Intent intent = new Intent(getApplicationContext(), + SearchCatalogListView.class); + startActivity(intent); + } + }); + } + + /** + * onDestroy The final call you receive before your activity is destroyed. + * This can happen either because the activity is finishing (someone called + * finish() on it, or because the system is temporarily destroying this + * instance of the activity to save space. You can distinguish between these + * two scenarios with the isFinishing() method. + * + */ + + protected void onDestroy() { + super.onDestroy(); + } + + /** + * onPause Called when the system is about to start resuming a previous + * activity. This is typically used to commit unsaved changes to persistent + * data, stop animations and other things that may be consuming CPU, etc. + * Implementations of this method must be very quick because the next + * activity will not be resumed until this method returns. Followed by + * either onResume() if the activity returns back to the front, or onStop() + * if it becomes invisible to the user. + * + */ + + protected void onPause() { + super.onPause(); + } + + /** + * onRestart Called after your activity has been stopped, prior to it being + * started again. Always followed by onStart(). + * + */ + + protected void onRestart() { + super.onRestart(); + } + + /** + * onResume Called when the activity will start interacting with the user. + * At this point your activity is at the top of the activity stack, with + * user input going to it. Always followed by onPause(). + * + */ + + protected void onResume() { + super.onResume(); + } + + /** + * onStart Called when the activity is becoming visible to the user. + * Followed by onResume() if the activity comes to the foreground, or + * onStop() if it becomes hidden. + * + */ + + protected void onStart() { + super.onStart(); + } + + /** + * onStop Called when the activity is no longer visible to the user because + * another activity has been resumed and is covering this one. This may + * happen either because a new activity is being started, an existing one is + * being brought in front of this one, or this one is being destroyed. + * + * Followed by either onRestart() if this activity is coming back to + * interact with the user, or onDestroy() if this activity is going away. + */ + + protected void onStop() { + super.onStop(); + } + + public void onClickFeature(View v) { + int id = v.getId(); + if (id == R.id.account_btn_check_out) { + startActivity(new Intent(getApplicationContext(), + ItemsCheckOutListView.class)); + + } else if (id == R.id.account_btn_holds) { + startActivity(new Intent(getApplicationContext(), + HoldsListView.class)); + + } else if (id == R.id.account_btn_fines) { + startActivity(new Intent(getApplicationContext(), + FinesActivity.class)); + + } else if (id == R.id.account_btn_book_bags) { + startActivity(new Intent(getApplicationContext(), + BookbagsListView.class)); + + } + + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/views/ApplicationPreferences.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/views/ApplicationPreferences.java new file mode 100644 index 0000000000..3b0ed13a6c --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/views/ApplicationPreferences.java @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.views; + +import java.util.Calendar; + +import org.evergreen_ils.R; +import org.evergreen_ils.globals.GlobalConfigs; +import org.evergreen_ils.services.NotificationAlert; +import org.evergreen_ils.services.PeriodicServiceBroadcastReceiver; +import org.evergreen_ils.services.ScheduledIntentService; +import org.evergreen_ils.auth.Const; + +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.net.ConnectivityManager; +import android.os.Bundle; +import android.preference.PreferenceActivity; +import android.preference.PreferenceManager; +import android.provider.Settings; +import android.widget.Toast; + +public class ApplicationPreferences extends PreferenceActivity implements + OnSharedPreferenceChangeListener { + + private final String TAG = ApplicationPreferences.class.getName(); + + private ProgressDialog progressDialog; + + private ApplicationPreferences reference; + + private Context context; + + private Thread coreFilesDownload = null; + + @Override + protected void onCreate(Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + addPreferencesFromResource(R.xml.preferences); + + context = this; + reference = this; + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + prefs.registerOnSharedPreferenceChangeListener(this); + } + + @Override + protected void onResume() { + super.onResume(); + reference = this; + } + + @Override + protected void onPause() { + super.onPause(); + reference = null; + } + + @Override + protected void onStop() { + super.onStop(); + reference = null; + } + + @Override + protected void onDestroy() { + super.onDestroy(); + reference = null; + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, + String key) { + + boolean httpAddressChange = false; + + boolean checkConnection = false; + + if (key.equals("notifications_enabled")) { + + if (sharedPreferences.getBoolean("notifications_enabled", false)) { + + Toast.makeText(context, "Set up notification updates", + Toast.LENGTH_SHORT).show(); + // if enabled register the update service to run once per day + // get a Calendar object with current time + Calendar cal = Calendar.getInstance(); + + Intent bRecvIntent = new Intent(this, + PeriodicServiceBroadcastReceiver.class); + bRecvIntent.setAction(ScheduledIntentService.ACTION); + // update the current intent if it exists + PendingIntent sender = PendingIntent.getBroadcast(this, + NotificationAlert.NOTIFICATION_INTENT + + PeriodicServiceBroadcastReceiver.INTENT_ID, + bRecvIntent, PendingIntent.FLAG_UPDATE_CURRENT); + + // Get the AlarmManager service + AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE); + am.setRepeating(AlarmManager.RTC, cal.getTimeInMillis(), + 10000 * ScheduledIntentService.SCHEDULE_TIME_INTERVAL, + sender); + } else { + Toast.makeText(context, "Disable notification updates", + Toast.LENGTH_SHORT).show(); + // cancel the service + + Intent bRecvIntent = new Intent(this, + PeriodicServiceBroadcastReceiver.class); + + // update the current intent if it exists + PendingIntent sender = PendingIntent.getBroadcast(this, + NotificationAlert.NOTIFICATION_INTENT + + PeriodicServiceBroadcastReceiver.INTENT_ID, + bRecvIntent, PendingIntent.FLAG_UPDATE_CURRENT); + + // Get the AlarmManager service + AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE); + // cancel the service + am.cancel(sender); + } + } + } + +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/views/splashscreen/LoadingTask.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/views/splashscreen/LoadingTask.java new file mode 100644 index 0000000000..74d442082e --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/views/splashscreen/LoadingTask.java @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.views.splashscreen; + +import org.evergreen_ils.R; +import org.evergreen_ils.accountAccess.AccountAccess; +import org.evergreen_ils.accountAccess.SessionNotFoundException; +import org.evergreen_ils.globals.GlobalConfigs; +import org.evergreen_ils.auth.Const; + +import android.accounts.Account; +import android.accounts.AccountManager; +import android.accounts.AccountManagerFuture; +import android.app.Activity; +import android.os.Bundle; +import android.util.Log; + +/** This is basically the same as an AsyncTask, except that it uses + * a Thread. Starting with HONEYCOMB, tasks are executed on a single thread and the 2nd + * AsyncTask doesn't start until the first finishes. + * + * @author kenstir + * + */ +public class LoadingTask { + private final String TAG = LoadingTask.class.getName(); + + public static final String TASK_OK = "OK"; + + public interface LoadingTaskListener { + void onPreExecute(); + void onProgressUpdate(String value); + void onPostExecute(String result); + } + + // This is the listener that will be told when this task is finished + private final LoadingTaskListener mListener; + private Activity mCallingActivity; + private AccountManager mAccountManager; + + public LoadingTask(LoadingTaskListener listener, Activity callingActivity) { + this.mListener = listener; + this.mCallingActivity = callingActivity; + mAccountManager = AccountManager.get(callingActivity); + } + + public void execute() { + Log.d(TAG, "execute>"); + final Thread t = new Thread(new Runnable() { + @Override + public void run() { + final String result = doInBackground(); + mCallingActivity.runOnUiThread(new Runnable() { + @Override + public void run() { + onPostExecute(result); + } + }); + } + }, TAG); + onPreExecute(); + t.start(); + } + + protected void publishProgress(final String progress) { + mCallingActivity.runOnUiThread(new Runnable() { + @Override + public void run() { + onProgressUpdate(progress); + } + }); + } + + //TODO: share some of this code with ScheduledIntentService.onHandleIntent + protected String doInBackground() { + final String tag ="doInBackground> "; + final String accountType = mCallingActivity.getString(R.string.ou_account_type); + Log.d(TAG, tag); + try { + Log.d(TAG, tag+"Loading resources"); + publishProgress("Loading resources"); + GlobalConfigs.getGlobalConfigs(mCallingActivity); // loads IDL + + Log.d(TAG, tag+"Signing in"); + publishProgress("Signing in"); + + AccountManagerFuture future = mAccountManager.getAuthTokenByFeatures(accountType, Const.AUTHTOKEN_TYPE, null, mCallingActivity, null, null, null, null); + Bundle bnd = future.getResult(); + Log.d(TAG, tag+"bnd="+bnd); + String auth_token = bnd.getString(AccountManager.KEY_AUTHTOKEN); + String account_name = bnd.getString(AccountManager.KEY_ACCOUNT_NAME); + Log.d(TAG, tag+"account_name="+account_name+" token="+auth_token); + if (account_name == null) + return "no account"; + + Log.d(TAG, tag+"Starting session"); + publishProgress("Starting session"); + AccountAccess ac = AccountAccess.getAccountAccess(GlobalConfigs.httpAddress); + + // auth token zen: try once and if it fails, invalidate the token and try again + boolean haveSession = false; + boolean retry = false; + try { + haveSession = ac.retrieveSession(auth_token, true); + } catch (SessionNotFoundException e) { + mAccountManager.invalidateAuthToken(accountType, auth_token); + retry = true; + } + if (retry) { + final Account account = new Account(account_name, accountType); + future = mAccountManager.getAuthToken(account, Const.AUTHTOKEN_TYPE, null, mCallingActivity, null, null); + bnd = future.getResult(); + Log.d(TAG, tag+"bnd="+bnd); + auth_token = bnd.getString(AccountManager.KEY_AUTHTOKEN); + account_name = bnd.getString(AccountManager.KEY_ACCOUNT_NAME); + Log.d(TAG, tag+"account_name="+account_name+" token="+auth_token); + if (account_name == null) + return "no account"; + haveSession = ac.retrieveSession(auth_token, true); + } + if (!haveSession) + return "no session"; + + Log.d(TAG, tag+"Retrieving bookbags"); + publishProgress("Retrieving bookbags"); + ac.retrieveBookbags(); + + return TASK_OK; + } catch (Exception e) { + Log.d(TAG, tag+"Caught exception", e); + String s = e.getMessage(); + if (s == null) s = "Cancelled"; + Log.d(TAG, tag+"returning "+s); + return s; + } + } + + protected void onPreExecute() { + Log.d(TAG, "onPreExecute> "); + mListener.onPreExecute(); + } + + protected void onProgressUpdate(String s) { + Log.d(TAG, "onProgressUpdate> "+s); + mListener.onProgressUpdate(s); + } + + protected void onPostExecute(String result) { + Log.d(TAG, "onPostExecute> "+result); + mListener.onPostExecute(result); + } +} diff --git a/Open-ILS/src/Android/core/src/org/evergreen_ils/views/splashscreen/SplashActivity.java b/Open-ILS/src/Android/core/src/org/evergreen_ils/views/splashscreen/SplashActivity.java new file mode 100644 index 0000000000..75092e3e4e --- /dev/null +++ b/Open-ILS/src/Android/core/src/org/evergreen_ils/views/splashscreen/SplashActivity.java @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2012 Evergreen Open-ILS + * @author Daniel-Octavian Rizea + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * or the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be usefull, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +package org.evergreen_ils.views.splashscreen; + +import org.evergreen_ils.R; +import org.evergreen_ils.globals.GlobalConfigs; +import org.evergreen_ils.searchCatalog.SearchCatalogListView; +import org.evergreen_ils.views.ApplicationPreferences; +import org.evergreen_ils.views.splashscreen.LoadingTask.LoadingTaskListener; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.ProgressBar; +import android.widget.TextView; +import org.evergreen_ils.auth.Const; + +public class SplashActivity extends Activity implements LoadingTaskListener { + + private static String TAG = "SplashActivity"; + private TextView mProgressText; + private Context mContext; + private ProgressBar mProgressBar; + private AlertDialog mAlertDialog; + private Button mRetryButton; + //private SharedPreferences prefs; + private LoadingTask mTask; + private static boolean mInitialized; + + public static boolean isAppInitialized() + { + return mInitialized; + } + + /** android may choose to initialize the app at a non-MAIN activity if the + * app crashed or for other reasons. In these cases we want to force sane + * initialization via the SplashActivity. + * + * used in all activity class's onCreate() like so: + * + * if (!SplashActivity.isInitialized) { + * SplashActivity.restartApp(this); + * return; + * } + * + * + * @param a + */ + public static void restartApp(Activity a) + { + Log.d(TAG, "restartApp> Restarting SplashActivity"); + final Intent i = new Intent(a, SplashActivity.class); + i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + a.startActivity(i); + a.finish(); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_splash); + + this.mContext = this; + + // make sure default values are set up for preferences + PreferenceManager.setDefaultValues(this, R.xml.preferences, false); + + mProgressText = (TextView) findViewById(R.id.action_in_progress); + mProgressBar = (ProgressBar) findViewById(R.id.activity_splash_progress_bar); + mRetryButton = (Button) findViewById(R.id.activity_splash_retry_button); + Log.d(TAG, "onCreate>"); + mRetryButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + startTask(); + } + }); + + GlobalConfigs.httpAddress = getString(R.string.ou_library_url); + startTask(); + } + + protected void startTask() { + Log.d(TAG, "startTask> task="+mTask); + if (mTask != null) + return; + mTask = new LoadingTask(this, this); + mTask.execute(); + } + + @Override + protected void onStop() { + super.onStop(); + if(mAlertDialog != null) { + mAlertDialog.dismiss(); + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + Log.d(TAG, "onActivityResult> "+requestCode+" "+resultCode); + } + + private void startApp() { + mInitialized = true; + Intent intent = new Intent(SplashActivity.this, SearchCatalogListView.class); + startActivity(intent); + finish(); + } + + @Override + public void onPreExecute() { + mRetryButton.setVisibility(View.GONE); + mProgressBar.setVisibility(View.VISIBLE); + } + + @Override + public void onProgressUpdate(String value) { + Log.d(TAG, "onProgressUpdate> "+value); + mProgressText.setText(value); + } + + @Override + public void onPostExecute(String result) { + Log.d(TAG, "onPostExecute> "+result); + mTask = null; + Log.d(TAG, "progressbar...gone"); + mProgressBar.setVisibility(View.GONE); + if (TextUtils.equals(result, LoadingTask.TASK_OK)) { + Log.d(TAG, "startApp"); + startApp(); + } else { + String extra_text; + if (!TextUtils.isEmpty(result)) + extra_text = "...Failed:\n" + result; + else + extra_text = "...Cancelled"; + Log.d(TAG, "progresstext += "+extra_text); + mProgressText.setText(mProgressText.getText() + extra_text); + Log.d(TAG, "retrybutton...visible"); + mRetryButton.setVisibility(View.VISIBLE); + } + } +} diff --git a/Open-ILS/src/Android/cwmars_app/AndroidManifest.xml b/Open-ILS/src/Android/cwmars_app/AndroidManifest.xml index bb99a1cd7c..549226e506 100644 --- a/Open-ILS/src/Android/cwmars_app/AndroidManifest.xml +++ b/Open-ILS/src/Android/cwmars_app/AndroidManifest.xml @@ -32,25 +32,25 @@ - + - + - + - + @@ -59,51 +59,51 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -59,51 +59,51 @@ - + - + - + - + - + - + - + - + - + - + - +