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
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.
<?xml version="1.0" encoding="utf-8"?>\r
<manifest xmlns:android="http://schemas.android.com/apk/res/android"\r
- package="org.evergreen.android"\r
+ package="org.evergreen_ils"\r
android:installLocation="auto"\r
android:versionCode="1"\r
android:versionName="1.0" >\r
\r
<!-- Notification receiver -->\r
<receiver\r
- android:name="org.evergreen.android.services.NotificationReceiver"\r
+ android:name="org.evergreen_ils.services.NotificationReceiver"\r
android:process=":remote" >\r
</receiver>\r
<!-- Receiver to reinit notifications on reboot -->\r
- <receiver android:name="org.evergreen.android.services.RebootReceiver" >\r
+ <receiver android:name="org.evergreen_ils.services.RebootReceiver" >\r
<intent-filter>\r
<action android:name="android.intent.action.BOOT_COMPLETED" />\r
</intent-filter>\r
</receiver>\r
- <receiver android:name="org.evergreen.android.services.PeriodicServiceBroadcastReceiver" >\r
+ <receiver android:name="org.evergreen_ils.services.PeriodicServiceBroadcastReceiver" >\r
<intent-filter>\r
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />\r
</intent-filter>\r
</receiver>\r
\r
- <service android:name="org.evergreen.android.services.ScheduledIntentService" >\r
+ <service android:name="org.evergreen_ils.services.ScheduledIntentService" >\r
</service>\r
\r
<activity\r
- android:name="org.evergreen.android.views.splashscreen.SplashActivity"\r
+ android:name="org.evergreen_ils.views.splashscreen.SplashActivity"\r
>\r
<!-- android:theme="@android:style/Theme.Light.NoTitleBar" -->\r
<intent-filter>\r
</intent-filter>\r
</activity>\r
<activity\r
- android:name="org.evergreen.android.views.AccountScreenDashboard"\r
+ android:name="org.evergreen_ils.views.AccountScreenDashboard"\r
android:theme="@android:style/Theme.Light.NoTitleBar" >\r
</activity>\r
- <activity android:name="org.evergreen.android.views.ApplicationPreferences" >\r
+ <activity android:name="org.evergreen_ils.views.ApplicationPreferences" >\r
</activity>\r
\r
<!-- Search -->\r
\r
- <activity android:name="org.evergreen.android.searchCatalog.SampleUnderlinesNoFade">\r
+ <activity android:name="org.evergreen_ils.searchCatalog.SampleUnderlinesNoFade">\r
</activity>\r
- <activity android:name="org.evergreen.android.searchCatalog.MoreCopyInformation" >\r
+ <activity android:name="org.evergreen_ils.searchCatalog.MoreCopyInformation" >\r
</activity>\r
- <activity android:name="org.evergreen.android.searchCatalog.SearchCatalogListView">\r
+ <activity android:name="org.evergreen_ils.searchCatalog.SearchCatalogListView">\r
</activity>\r
- <activity android:name="org.evergreen.android.searchCatalog.AdvancedSearchActivity" >\r
+ <activity android:name="org.evergreen_ils.searchCatalog.AdvancedSearchActivity" >\r
</activity>\r
<activity\r
- android:name="org.evergreen.android.barcodescan.CaptureActivity"\r
+ android:name="org.evergreen_ils.barcodescan.CaptureActivity"\r
android:screenOrientation="landscape"\r
android:theme="@android:style/Theme.NoTitleBar"\r
android:windowSoftInputMode="stateAlwaysHidden" >\r
</activity>\r
\r
<!-- Checkout Activities -->\r
- <activity android:name="org.evergreen.android.accountAccess.checkout.ItemsCheckOutListView" >\r
+ <activity android:name="org.evergreen_ils.accountAccess.checkout.ItemsCheckOutListView" >\r
</activity>\r
\r
<!-- Holds Activities -->\r
- <activity android:name="org.evergreen.android.accountAccess.holds.HoldsListView" >\r
+ <activity android:name="org.evergreen_ils.accountAccess.holds.HoldsListView" >\r
</activity>\r
- <activity android:name="org.evergreen.android.accountAccess.holds.PlaceHold" >\r
+ <activity android:name="org.evergreen_ils.accountAccess.holds.PlaceHold" >\r
</activity>\r
- <activity android:name="org.evergreen.android.accountAccess.holds.HoldDetails" >\r
+ <activity android:name="org.evergreen_ils.accountAccess.holds.HoldDetails" >\r
</activity>\r
\r
<!-- Fines Activities -->\r
- <activity android:name="org.evergreen.android.accountAccess.fines.FinesActivity" >\r
+ <activity android:name="org.evergreen_ils.accountAccess.fines.FinesActivity" >\r
</activity>\r
\r
<!-- Bookbags -->\r
- <activity android:name="org.evergreen.android.accountAccess.bookbags.BookbagsListView" >\r
+ <activity android:name="org.evergreen_ils.accountAccess.bookbags.BookbagsListView" >\r
</activity>\r
- <activity android:name="org.evergreen.android.accountAccess.bookbags.BookBagDetails" >\r
+ <activity android:name="org.evergreen_ils.accountAccess.bookbags.BookBagDetails" >\r
</activity>\r
\r
<activity\r
android:layout_height="fill_parent"
android:layout_centerInParent="true"/>
- <org.evergreen.android.barcodescan.ViewfinderView
+ <org.evergreen_ils.barcodescan.ViewfinderView
android:id="@+id/viewfinder_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
android:layout_marginLeft="4dip"
android:layout_marginRight="4dip"
/>
- <org.evergreen.android.utils.ui.UnderlinePageIndicator
+ <org.evergreen_ils.utils.ui.UnderlinePageIndicator
android:id="@+id/indicator"
android:layout_height="2dp"
android:layout_width="fill_parent"
+++ /dev/null
-/*
- * 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;
-
-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.android.R;
-import org.evergreen.android.accountAccess.bookbags.BookBag;
-import org.evergreen.android.accountAccess.bookbags.BookBagItem;
-import org.evergreen.android.accountAccess.checkout.CircRecord;
-import org.evergreen.android.accountAccess.fines.FinesRecord;
-import org.evergreen.android.accountAccess.holds.HoldRecord;
-import org.evergreen.android.globals.Utils;
-import org.evergreen.android.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<BookBag> bookBags = new ArrayList<BookBag>();
-
- /** 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<CircRecord> getItemsCheckedOut()
- throws SessionNotFoundException {
-
- ArrayList<CircRecord> circRecords = new ArrayList<CircRecord>();
-
- Object resp = Utils.doRequest(conn, SERVICE_ACTOR,
- METHOD_FETCH_CHECKED_OUT_SUM, authToken, new Object[] {
- authToken, userID });
- if (resp == null)
- return circRecords;
- Map<String, ?> resp_map = ((Map<String, ?>) resp);
-
- if (resp_map.get("out") != null) {
- List<String> out_id = (List<String>) 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<String> overdue_id = (List<String>) 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<CircRecord>() {
- @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<String, Integer> complexParam = new HashMap<String, Integer>();
- 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<String, String> resp = (Map<String, String>) 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<HoldRecord> getHolds() throws SessionNotFoundException {
-
- ArrayList<HoldRecord> holds = new ArrayList<HoldRecord>();
-
- // fields of interest : expire_time
- List<OSRFObject> 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<OSRFObject>) 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<Object>) 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<Object>) 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<Object>) 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<String, Object> param = new HashMap<String, Object>();
-
- param.put("cache", 1);
-
- ArrayList<String> fieldsList = new ArrayList<String>();
- fieldsList.add("label");
- fieldsList.add("record");
-
- param.put("fields", fieldsList);
- HashMap<String, Integer> queryParam = new HashMap<String, Integer>();
- // PART_ID use "target field in hold"
- queryParam.put("id", hold.getInt("target"));
- param.put("query", queryParam);
-
- // returns [{record:id, label=part label}]
-
- List<Object> part = (List<Object>) Utils.doRequest(conn,
- SERVICE_FIELDER, "open-ils.fielder.bmp.atomic", cm,
- new Object[] { param });
-
- Map<String, ?> partObj = (Map<String, ?>) 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<Object>) 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<String, Integer> map = (Map<String, Integer>)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<String, String>) map).get("textcode");
- resp[2] = ((Map<String, String>) 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<String, Integer> 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<String, Integer> getHoldPreCreateInfo(Integer recordID,
- Integer pickup_lib) {
-
- HashMap<String, Integer> param = new HashMap<String, Integer>();
-
- param.put("pickup_lib", pickup_lib);
- param.put("record", recordID);
-
- Map<String, ?> response = (Map<String, ?>) 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<String, Integer> map = new HashMap<String, Integer>();
- 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<FinesRecord> getTransactions()
- throws SessionNotFoundException {
-
- ArrayList<FinesRecord> finesRecords = new ArrayList<FinesRecord>();
-
- Object transactions = Utils.doRequest(conn, SERVICE_ACTOR,
- METHOD_FETCH_TRANSACTIONS, authToken, new Object[] {
- authToken, userID });
-
- // get Array
-
- List<Map<String, OSRFObject>> list = (List<Map<String, OSRFObject>>) transactions;
-
- for (int i = 0; i < list.size(); i++) {
-
- Map<String, OSRFObject> 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<OSRFObject> bookbags = (List<OSRFObject>) response;
-
- ArrayList<BookBag> bookBagObj = new ArrayList<BookBag>();
- // 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<BookBag> 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<String, ?> map = (Map<String, ?>) Utils.doRequest(conn,
- SERVICE_ACTOR, METHOD_FLESH_PUBLIC_CONTAINER, authToken,
- new Object[] { authToken, "biblio", bookbagID });
-
- List<OSRFObject> items = new ArrayList<OSRFObject>();
-
- try{
- items = (List<OSRFObject>) 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 });
- }
-}
+++ /dev/null
-/*
- * 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;
-
-}
+++ /dev/null
-/*
- * 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;
- }
-
-}
+++ /dev/null
-/*
- * 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;
-
-}
+++ /dev/null
-/*
- * 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<BookBagItem> 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<BookBagItem>();
-
- String pub_visible = object.getString("pub");
-
- if (pub_visible.equals("f"))
- this.shared = false;
- else
- this.shared = true;
- }
-
-}
+++ /dev/null
-/*
- * 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<BookBagItem> 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<BookBagItem>();
- 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<RecordInfo> records = new ArrayList<RecordInfo>();
- ArrayList<Integer> ids = new ArrayList<Integer>();
-
- 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<BookBagItem> {
- private static final String tag = "BookbagArrayAdapter";
-
- private TextView title;
- private TextView author;
- private Button remove;
-
- private List<BookBagItem> records = new ArrayList<BookBagItem>();
-
- public BookBagItemsArrayAdapter(Context context,
- int textViewResourceId, List<BookBagItem> 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;
- }
- }
-}
+++ /dev/null
-/*
- * 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");
-
- }
-}
+++ /dev/null
-/*
- * 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<BookBag> 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<BookBag>();
- 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<BookBag> {
- private static final String tag = "BookbagArrayAdapter";
-
- private TextView name;
- private TextView items;
- private CheckBox shared;
- private Button detailsButton;
-
- private List<BookBag> records = new ArrayList<BookBag>();
-
- public BookBagsArrayAdapter(Context context, int textViewResourceId,
- List<BookBag> 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;
- }
- }
-}
+++ /dev/null
-/*
- * 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;
- }
-
-}
+++ /dev/null
-/*
- * 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<CircRecord> 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<CircRecord>();
- 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<CircRecord> {
- private static final String tag = "CheckoutArrayAdapter";
-
- private TextView recordTitle;
- private TextView recordAuthor;
- private TextView recordDueDate;
- private TextView recordRenewals;
- private TextView renewButton;
-
- private List<CircRecord> records = new ArrayList<CircRecord>();
-
- public CheckOutArrayAdapter(Context context, int textViewResourceId,
- List<CircRecord> 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;
- }
- }
-}
+++ /dev/null
-/*
- * 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<FinesRecord> finesRecords = new ArrayList<FinesRecord>();
- 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<FinesRecord> frecords = null;
- try {
- frecords = ac.getTransactions();
- } catch (SessionNotFoundException e) {
- try {
- if (ac.reauthenticate(FinesActivity.this))
- frecords = ac.getTransactions();
- } catch (Exception e1) {
- }
- }
-
- final ArrayList<FinesRecord> 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<FinesRecord> {
- private static final String tag = "CheckoutArrayAdapter";
-
- private TextView fineTitle;
- private TextView fineAuthor;
- private TextView fineBalanceOwed;
- private TextView fineStatus;
-
- private List<FinesRecord> records = new ArrayList<FinesRecord>();
-
- public OverdueMaterialsArrayAdapter(Context context,
- int textViewResourceId, List<FinesRecord> 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;
- }
- }
-}
+++ /dev/null
-/*
- * 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";
-
- }
-}
+++ /dev/null
-/*
- * 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<String> list = new ArrayList<String>();
- 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<String> adapter = new ArrayAdapter<String>(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));
- }
-
-}
+++ /dev/null
-/*
- * 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 "";
- }
- }
-
-}
+++ /dev/null
-/*
- * 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<HoldRecord> 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<HoldRecord>();
- 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<HoldRecord> {
- private static final String tag = "CheckoutArrayAdapter";
-
- private TextView holdTitle;
- private TextView holdAuthor;
- private TextView status;
- private ImageView hold_icon;
-
- private List<HoldRecord> records = new ArrayList<HoldRecord>();
-
- public HoldsArrayAdapter(Context context, int textViewResourceId,
- List<HoldRecord> 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;
- }
- }
-}
+++ /dev/null
-/*
- * 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<String> list = new ArrayList<String>();
- 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<String> adapter = new ArrayAdapter<String>(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));
- }
-
-}
+++ /dev/null
-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<BarcodeFormat> 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();
- }
-
-}
+++ /dev/null
-
-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<BarcodeFormat> 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();
- }
- }
-
-}
+++ /dev/null
-/*
- * 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<BarcodeFormat> PRODUCT_FORMATS;
- static final Vector<BarcodeFormat> ONE_D_FORMATS;
- static final Vector<BarcodeFormat> QR_CODE_FORMATS;
- static final Vector<BarcodeFormat> DATA_MATRIX_FORMATS;
- static {
- PRODUCT_FORMATS = new Vector<BarcodeFormat>(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<BarcodeFormat>(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<BarcodeFormat>(1);
- QR_CODE_FORMATS.add(BarcodeFormat.QR_CODE);
- DATA_MATRIX_FORMATS = new Vector<BarcodeFormat>(1);
- DATA_MATRIX_FORMATS.add(BarcodeFormat.DATA_MATRIX);
- }
-
- private DecodeFormatManager() {}
-
- static Vector<BarcodeFormat> parseDecodeFormats(Intent intent) {
- List<String> 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<BarcodeFormat> parseDecodeFormats(Uri inputUri) {
- List<String> 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<BarcodeFormat> parseDecodeFormats(Iterable<String> scanFormats,
- String decodeMode) {
- if (scanFormats != null) {
- Vector<BarcodeFormat> formats = new Vector<BarcodeFormat>();
- 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;
- }
-
-}
+++ /dev/null
-/*
- * 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<DecodeHintType, Object> 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();
- }
- }
- }
-
-}
+++ /dev/null
-/*
- * 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<DecodeHintType, Object> hints;
- private Handler handler;
- private final CountDownLatch handlerInitLatch;
- private CameraManager cameraManager;
- DecodeThread(CaptureActivity activity,
- Vector<BarcodeFormat> decodeFormats,
- String characterSet,
- ResultPointCallback resultPointCallback, CameraManager cameraManager) {
-
- this.activity = activity;
- handlerInitLatch = new CountDownLatch(1);
- this.cameraManager = cameraManager;
- hints = new Hashtable<DecodeHintType, Object>(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<BarcodeFormat>();
- 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();
- }
-
-}
+++ /dev/null
-/*
- * 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();
- }
-
-}
+++ /dev/null
-package org.evergreen.android.barcodescan;\r
-\r
-import android.content.Context;\r
-import android.graphics.Color;\r
-import android.widget.TextView;\r
-import android.widget.Toast;\r
-\r
-/**\r
- * \r
- * @author George Oprina\r
- * \r
- * 08.06.2011\r
- */\r
-\r
-public class Functions {\r
-\r
- // makes toast length short\r
- public static void makeToast(String s, Context c) {\r
- CharSequence text = s;\r
- int duration = Toast.LENGTH_SHORT;\r
-\r
- Toast toast = Toast.makeText(c, text, duration);\r
- toast.show();\r
- }\r
-\r
- // makes toast selectable length\r
- public static void makeToast(String s, Context c, int length) {\r
- CharSequence text = s;\r
- int duration = Toast.LENGTH_SHORT;\r
-\r
- if (length == 1)\r
- duration = Toast.LENGTH_LONG;\r
-\r
- Toast toast = Toast.makeText(c, text, duration);\r
- toast.show();\r
- }\r
-\r
- // makes text view from string\r
- public static TextView makeTextView(String s, Context c) {\r
- TextView text = new TextView(c);\r
- text.setBackgroundColor(Color.WHITE);\r
- text.setText(s);\r
- text.setTextColor(Color.BLACK);\r
- return text;\r
- }\r
-\r
- // thread sleep\r
- public static void sleep(int msec) {\r
- try {\r
- Thread.sleep(msec);\r
- } catch (InterruptedException e) {\r
- e.printStackTrace();\r
- }\r
- }\r
-\r
-}\r
+++ /dev/null
-/*
- * 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() {
- }
- }
-}
+++ /dev/null
-/*
- * 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;
- }
- }
- }
-
-}
+++ /dev/null
-/*
- * 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<CheckBoxPreference> checked = new ArrayList<CheckBoxPreference>(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)));
- }
- }
-
-}
+++ /dev/null
-/*
- * 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);
- }
-
-}
+++ /dev/null
-/*
- * 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<ResultPoint> possibleResultPoints;
- private List<ResultPoint> 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<ResultPoint>(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<ResultPoint> currentPossible = possibleResultPoints;
- List<ResultPoint> currentLast = lastPossibleResultPoints;
- int frameLeft = frame.left;
- int frameTop = frame.top;
- if (currentPossible.isEmpty()) {
- lastPossibleResultPoints = null;
- } else {
- possibleResultPoints = new ArrayList<ResultPoint>(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<ResultPoint> 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();
- }
- }
- }
-
-}
+++ /dev/null
-/*
- * 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");
- }
- }
-
-}
+++ /dev/null
-/*
- * 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<String> 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;
- }
-
-}
+++ /dev/null
-/*
- * 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);
- }
-
-}
+++ /dev/null
-/*
- * 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);
- }
- }
-
-}
+++ /dev/null
-/*
- * 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");
- }
- }
-
-}
+++ /dev/null
-/*
- * 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", "");
- }
-}
+++ /dev/null
-/*
- * 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<Class, ReflectionManager> rmMap = new HashMap<Class, ReflectionManager>();
-
- @SuppressWarnings("rawtypes")
- private static HashMap<Class, DefaultDAO> daoMap = new HashMap<Class, DefaultDAO>();
-
- /**
- * 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 <T> ReflectionManager getReflectionManagerInstance(
- Class<T> 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 <T>
- * the generic type
- * @param cls
- * the class
- * @param tableName
- * the table name
- * @return the DAO instance
- */
- @SuppressWarnings("unchecked")
- public static synchronized <T> DefaultDAO<T> getDAOInstance(
- Context context, Class<T> cls, String tableName) {
- if (daoMap.containsKey(cls))
- return daoMap.get(cls);
- DefaultDAO<T> dao = new DefaultDAO<T>(cls,
- DatabaseManager.getDBHelper(context),
- DatabaseManager.getReflectionManagerInstance(cls), tableName);
- daoMap.put(cls, dao);
- return dao;
- }
-}
+++ /dev/null
-/*
- * 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;
-}
+++ /dev/null
-/*
- * 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<Organisation> 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<Organisation>();
-
- 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<Organisation>();
-
- // 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<orgList.size(); ++i) {
- Organisation org = new Organisation();
- List orgItem = (List) orgList.get(i);
- org.id= (Integer)orgItem.get(0);
- org.level = (Integer)orgItem.get(1);
- org.parent = (Integer)orgItem.get(2);
- org.name = (String)orgItem.get(3);
- org.isVisible = (Integer)orgItem.get(4);
- org.shortName = (String)orgItem.get(5);
- if (org.isVisible == 0) {
- continue;
- }
-
- organisations.add(org);
- }
-
- /*
- for (int i=0; i<organisations.size(); ++i) {
- Log.d(TAG, "getOrg presort org["+i+"]= id:"+organisations.get(i).id+" parent:"+organisations.get(i).parent+" name:"+organisations.get(i).name);
- }
- */
- Collections.sort(organisations, new Comparator<Organisation>() {
- @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<organisations.size(); ++i) {
- Log.d(TAG, "getOrg postsort org["+i+"]= id:"+organisations.get(i).id+" parent:"+organisations.get(i).parent+" name:"+organisations.get(i).name);
- }
- */
-
- long duration_ms = System.currentTimeMillis() - start_ms;
- Log.d("init", "Loading organisations took "+duration_ms+"ms");
- loadedOrgTree = true;
- }
- }
-
- public void getCopyStatusesAvailable(ConnectivityManager cm) {
-
- SearchCatalog search = SearchCatalog.getInstance(cm);
-
- try {
- search.getCopyStatuses();
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- public void getOrgHiddentDepth() {
-
- // logic can be found in the opac_utils.js file in web/opac/common/js
-
- for (int i = 0; i < organisations.size(); i++) {
- AccountAccess ac = AccountAccess.getAccountAccess();
- try {
- Object obj = ac.fetchOrgSettings(organisations.get(i).id,
- "opac.org_unit_hiding.depth");
- } catch (SessionNotFoundException e) {
- }
-
- }
-
- }
-
- public static String getStringDate(Date date) {
-
- final SimpleDateFormat sdf = new SimpleDateFormat(
- GlobalConfigs.datePattern);
-
- return sdf.format(date);
-
- }
-
- // parse from opac methods query results to Java date
- public static Date parseDate(String dateString) {
-
- if (dateString == null)
- return null;
-
- Date date = null;
- final SimpleDateFormat sdf = new SimpleDateFormat(
- GlobalConfigs.datePattern);
-
- try {
- date = sdf.parse(dateString);
- } catch (ParseException e) {
- e.printStackTrace();
- }
-
- return date;
- }
-
- // parse from opac methods query result to boolean
- public static boolean parseBoolean(String boolString) {
- return (boolString != null && boolString.equals("t"));
- }
-
- public String getOrganizationName(int id) {
-
- for (int i = 0; i < organisations.size(); i++) {
- if (organisations.get(i).id == id)
- return organisations.get(i).name;
- }
-
- return null;
- }
-}
+++ /dev/null
-/*
- * 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.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-
-public class ShowServerNotAvailableRunnable implements Runnable {
-
- private Context context;
-
- public ShowServerNotAvailableRunnable(Context context) {
- this.context = context;
- }
-
- @Override
- public void run() {
- AlertDialog alertDialog = new AlertDialog.Builder(context).create();
- alertDialog.setTitle("Error");
- alertDialog.setMessage("There is no network connectivity to "
- + GlobalConfigs.httpAddress);
- alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int id) {
- dialog.dismiss();
- }
- });
-
- alertDialog.show();
- }
-
-}
\ No newline at end of file
+++ /dev/null
-/*
- * 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.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-
-class ShowSessionNotAvailableRunnable implements Runnable {
-
- public Context context;
-
- public ShowSessionNotAvailableRunnable(Context context) {
- this.context = context;
- }
-
- @Override
- public void run() {
- AlertDialog alertDialog = new AlertDialog.Builder(context).create();
- alertDialog.setTitle("Error");
- alertDialog.setMessage("No session");
- alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int id) {
- dialog.dismiss();
- }
- });
-
- alertDialog.show();
- }
-
-}
\ No newline at end of file
+++ /dev/null
-/*
- * 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 java.io.BufferedInputStream;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.Map;
-
-import android.os.Looper;
-import android.text.TextUtils;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.evergreen.android.accountAccess.SessionNotFoundException;
-import org.opensrf.Method;
-import org.opensrf.net.http.GatewayRequest;
-import org.opensrf.net.http.HttpConnection;
-import org.opensrf.net.http.HttpRequest;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.net.ConnectivityManager;
-import android.util.Log;
-import android.widget.ImageView;
-
-public class Utils {
- private static final String TAG = "osrf";
-
- /**
- * Gets the net page content.
- *
- * @param url
- * the url of the page to be retrieved
- * @return the net page content
- */
- public static String getNetPageContent(String url) {
-
- String result = "";
-
- HttpResponse response = null;
-
- try {
- HttpClient client = new DefaultHttpClient();
- HttpGet request = new HttpGet(url);
- response = client.execute(request);
- } catch (Exception e) {
- Log.d(TAG, "Exception to GET page " + url);
- }
- StringBuilder str = null;
-
- try {
- InputStream in = response.getEntity().getContent();
- BufferedReader reader = new BufferedReader(
- new InputStreamReader(in));
- str = new StringBuilder();
- String line = null;
- while ((line = reader.readLine()) != null) {
- str.append(line);
- }
- in.close();
- } catch (Exception e) {
- System.err
- .println("Error in retrieving response " + e.getMessage());
- }
-
- result = str.toString();
-
- return result;
- }
-
- public static InputStream getNetInputStream(String url) {
-
- InputStream in = null;
-
- HttpResponse response = null;
-
- try {
- HttpClient client = new DefaultHttpClient();
- HttpGet request = new HttpGet(url);
- response = client.execute(request);
- } catch (Exception e) {
- Log.d(TAG, "Exception to GET page " + url);
- }
-
- try {
- in = response.getEntity().getContent();
-
- return in;
- } catch (Exception e) {
- System.err
- .println("Error in retrieving response " + e.getMessage());
- }
-
- return in;
- }
-
- public static boolean checkIfNetAddressIsReachable(String url) {
-
- // The old method of fetching the URL to see if the net is "reachable" was not good;
- // it wasted bandwidth and time. For now just check if the url is empty.
- return (url.length() > 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<String, String>) 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);
- }
-
-}
+++ /dev/null
-/*
- * 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();
- }
- });
-
- }
-
-}
+++ /dev/null
-/*
- * 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<String, Integer>) map).get("org_unit");
- this.count = ((Map<String, Integer>) map).get("count");
- this.available = ((Map<String, Integer>) map).get("available");
- this.depth = ((Map<String, Integer>) map).get("depth");
- this.unshadow = ((Map<String, Integer>) map).get("unshadow");
-
- Log.d(TAG, org_id + " " + available + " " + count);
- }
-
-}
+++ /dev/null
-/*
- * 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<String, String> statuses;
-
- // the hash from the request method
- private HashMap<Integer, Integer> hashValCopy;
-
- // global, it is initialized when orgTree and fm_ild is downloaded
-
- public static LinkedHashMap<String, String> availableOrgStatuses;
-
- public LinkedHashMap<String, String> statusInformation = null;
-
- public CopyInformation(List<Object> list) {
-
- org_id = Integer.parseInt((String) list.get(0));
- call_number_sufix = (String) list.get(2);
- copy_location = (String) list.get(4);
-
- hashValCopy = (HashMap<Integer, Integer>) list.get(5);
-
- statusInformation = new LinkedHashMap<String, String>();
-
- Set<Entry<String, String>> set = availableOrgStatuses.entrySet();
-
- Iterator<Entry<String, String>> it = set.iterator();
-
- while (it.hasNext()) {
- Entry<String, String> 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()));
- }
- }
- }
-
-}
+++ /dev/null
-/*
- * 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.
- *
- * <p>
- * It requires the INTERNET permission, which should be added to your
- * application's manifest file.
- * </p>
- *
- * 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<String, Void, Bitmap> {
- private String url;
- private final WeakReference<ImageView> imageViewReference;
-
- public BitmapDownloaderTask(ImageView imageView) {
- imageViewReference = new WeakReference<ImageView>(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.
- *
- * <p>
- * 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.
- * </p>
- */
- static class DownloadedDrawable extends ColorDrawable {
- private final WeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference;
-
- public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) {
- super(Color.BLACK);
-
- bitmapDownloaderTaskReference = new WeakReference<BitmapDownloaderTask>(
- 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<String, Bitmap> sHardBitmapCache = new LinkedHashMap<String, Bitmap>(
- HARD_CACHE_CAPACITY / 2, 0.75f, true) {
- @Override
- protected boolean removeEldestEntry(
- LinkedHashMap.Entry<String, Bitmap> 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<Bitmap>(eldest.getValue()));
- return true;
- } else
- return false;
- }
- };
-
- // Soft cache for bitmaps kicked out of hard cache
- private final static ConcurrentHashMap<String, SoftReference<Bitmap>> sSoftBitmapCache = new ConcurrentHashMap<String, SoftReference<Bitmap>>(
- 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<Bitmap> 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);
- }
-}
+++ /dev/null
-/*
- * 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<Entry<String, String>> set = info.statusInformation.entrySet();
-
- Iterator<Entry<String, String>> it = set.iterator();
-
- while (it.hasNext()) {
-
- Entry<String, String> 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));
-
- }
-
- }
-
- }
-}
+++ /dev/null
-/*
- * 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() {
-
- }
-}
+++ /dev/null
-/*
- * 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<CopyCountInformation> copyCountListInfo = null;
-
- public List<CopyInformation> copyInformationList = null;
-
- public RecordInfo() {
- this.title = "Test title";
- this.author = "Test author";
- this.pubdate = "Publication date";
- copyInformationList = new ArrayList<CopyInformation>();
-
- // marks the fact that this is a record made from no info
- this.dummy = true;
- }
-
- public RecordInfo(OSRFObject info) {
- copyInformationList = new ArrayList<CopyInformation>();
- 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<String, ?> subjectMap = (Map<String, ?>) info.get("subject");
-
- this.subject = "";
-
- int no = subjectMap.entrySet().size();
- int i = 0;
- for (Entry<String, ?> 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<String> 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());
- }
- ;
-
- }
-}
+++ /dev/null
-/*
- * 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<RecordInfo> records;
-
- private Button myAccountButton;
-
- private Button homeButton;
-
- private TextView headerTitle;
-
- private SearchCatalog search;
-
- private ArrayList<RecordInfo> 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<RecordInfo>) 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
+++ /dev/null
-/*
- * 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<RecordInfo> getSearchResults(String searchWords,
- Integer offset) {
-
- searchText = searchWords;
-
- ArrayList<RecordInfo> resultsRecordInfo = new ArrayList<RecordInfo>();
-
- Method method = new Method(METHOD_MULTICLASS_QUERY);
-
- HashMap complexParm = new HashMap<String, Integer>();
-
- 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<String> ids = new ArrayList<String>();
-
- Log.d(TAG, "Sync Response: " + resp);
- if (resp == null)
- return resultsRecordInfo; // search failed or server crashed
-
- Map<String, ?> response = (Map<String, ?>) resp;
-
- Log.d(TAG, " ids : " + response.get("ids") + " ");
-
- List<List<String>> result_ids;
- result_ids = (List<List<String>>) 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<Object>> list = (List<List<Object>>) 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<OSRFObject> ccs_list = (List<OSRFObject>) Utils.doRequestSimple(
- conn, SERVICE, METHOD_COPY_STATUS_ALL, new Object[] {});
-
- CopyInformation.availableOrgStatuses = new LinkedHashMap<String, String>();
-
- 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<RecordInfo> getRecordsInfo(ArrayList<Integer> ids) {
-
- ArrayList<RecordInfo> recordInfoArray = new ArrayList<RecordInfo>();
-
- 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<CopyCountInformation> getCopyCount(Integer recordID,
- Integer orgID) {
-
- List<?> list = (List<?>) Utils.doRequestSimple(conn, SERVICE,
- METHOD_GET_COPY_COUNT, new Object[] { orgID, recordID, "" });
-
- ArrayList<CopyCountInformation> copyInfoList = new ArrayList<CopyCountInformation>();
-
- 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;
- }
-
-}
+++ /dev/null
-/*
- * 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<RecordInfo> recordList;
-
- private EditText searchText;
-
- private ImageButton searchButton;
-
- private SearchCatalog search;
-
- private ListView lv;
-
- private SearchArrayAdapter adapter;
-
- private Context context;
-
- private ProgressDialog progressDialog;
-
- private ArrayList<RecordInfo> 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<BookBag> 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<RecordInfo>();
-
- // 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<RecordInfo>();
-
- 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<String> list = new ArrayList<String>();
- 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<String> adapter = new ArrayAdapter<String>(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<RecordInfo> records = (ArrayList)data.getSerializableExtra("recordList");
-
- recordList.clear();
- for(int i=0;i<records.size();i++){
- recordList.add(records.get(i));
- }
- adapter.notifyDataSetChanged();
-
- searchResultsNumber.setText(adapter
- .getCount()
- + " out of "
- + search.visible);
- }
- break;
-
- case AdvancedSearchActivity.RESULT_ADVANCED_SEARCH: {
- Log.d(TAG,
- "result text" + data.getStringExtra("advancedSearchText"));
- searchText.setText(data.getStringExtra("advancedSearchText"));
- Thread searchThread = new Thread(searchForResultsRunnable);
- searchThread.start();
- }
- break;
-
- case CaptureActivity.BARCODE_SEARCH: {
- searchText.setText("identifier|isbn: "
- + data.getStringExtra("barcodeValue"));
- Thread searchThread = new Thread(searchForResultsRunnable);
- searchThread.start();
- }
-
- }
- }
-
- class SearchArrayAdapter extends ArrayAdapter<RecordInfo> {
-
- private static final String tag = "SearchArrayAdapter";
- private Context context;
- private ImageView recordImage;
- private TextView recordTitle;
- private TextView recordAuthor;
- private TextView recordPublisher;
-
- private List<RecordInfo> records = new ArrayList<RecordInfo>();
-
- public SearchArrayAdapter(Context context, int textViewResourceId,
- List<RecordInfo> 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;
- }
- }
-}
+++ /dev/null
-/*
- * 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
- + "]";
- }
-}
+++ /dev/null
-/*
- * 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);
-
- }
-
-}
+++ /dev/null
-/*
- * 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);
- }
- }
-
- }
-
- }
-
-}
+++ /dev/null
-/*
- * 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);
- }
-
- }
-
-}
+++ /dev/null
-/*
- * 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<Bundle> 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<CircRecord> circRecords = new ArrayList<CircRecord>();
-
- // get the circ records
- try {
- circRecords = accountAccess.getItemsCheckedOut();
- } catch (SessionNotFoundException e) {
- // auth just earlier realized, not supose to happen
- }
-
- DefaultDAO<NotificationAlert> daoNotifications = DatabaseManager
- .getDAOInstance(this, NotificationAlert.class,
- NotificationAlert.tableName);
- daoNotifications.open();
-
- // Fetch all alarms from database
- List<NotificationAlert> 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);
- }
- */
- }
-}
+++ /dev/null
-/*
- * 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);
- }
-}
+++ /dev/null
-/*
- * 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<BookBag> 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<Entry<String, String>> set = info.statusInformation.entrySet();
-
- Iterator<Entry<String, String>> it = set.iterator();
-
- while (it.hasNext()) {
-
- Entry<String, String> 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));
-
- }
-
- }
-
- }
-}
+++ /dev/null
-/*
- * 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;
- }
- }
-}
+++ /dev/null
-/*
- * 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);
-
- /**
- * <p>
- * Set the current page of both the ViewPager and indicator.
- * </p>
- *
- * <p>
- * This <strong>must</strong> be used if you need to set the page before the
- * views are drawn on screen (e.g., default start page).
- * </p>
- *
- * @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();
-}
+++ /dev/null
-/*
- * 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;
- }
- }
-}
+++ /dev/null
-/*\r
- * Copyright (C) 2012 Evergreen Open-ILS\r
- * @author Daniel-Octavian Rizea\r
- * \r
- * This program is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU General Public License\r
- * as published by the Free Software Foundation; either version 2\r
- * or the License, or (at your option) any later version.\r
- * \r
- * This program is distributed in the hope that it will be usefull,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- * \r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software \r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\r
- * \r
- */\r
-package org.evergreen.android.utils.ui;\r
-\r
-import android.os.Bundle;\r
-import android.support.v4.app.Fragment;\r
-import android.view.Gravity;\r
-import android.view.LayoutInflater;\r
-import android.view.View;\r
-import android.view.ViewGroup;\r
-import android.widget.LinearLayout;\r
-import android.widget.LinearLayout.LayoutParams;\r
-import android.widget.TextView;\r
-\r
-public final class TestFragment extends Fragment {\r
- private static final String KEY_CONTENT = "TestFragment:Content";\r
-\r
- public static TestFragment newInstance(String content) {\r
- TestFragment fragment = new TestFragment();\r
-\r
- StringBuilder builder = new StringBuilder();\r
- for (int i = 0; i < 20; i++) {\r
- builder.append(content).append(" ");\r
- }\r
- builder.deleteCharAt(builder.length() - 1);\r
- fragment.mContent = builder.toString();\r
-\r
- return fragment;\r
- }\r
-\r
- private String mContent = "???";\r
-\r
- @Override\r
- public void onCreate(Bundle savedInstanceState) {\r
- super.onCreate(savedInstanceState);\r
-\r
- if ((savedInstanceState != null)\r
- && savedInstanceState.containsKey(KEY_CONTENT)) {\r
- mContent = savedInstanceState.getString(KEY_CONTENT);\r
- }\r
- }\r
-\r
- @Override\r
- public View onCreateView(LayoutInflater inflater, ViewGroup container,\r
- Bundle savedInstanceState) {\r
- TextView text = new TextView(getActivity());\r
- text.setGravity(Gravity.CENTER);\r
- text.setText(mContent);\r
- text.setTextSize(20 * getResources().getDisplayMetrics().density);\r
- text.setPadding(20, 20, 20, 20);\r
-\r
- LinearLayout layout = new LinearLayout(getActivity());\r
- layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,\r
- LayoutParams.MATCH_PARENT));\r
- layout.setGravity(Gravity.CENTER);\r
- layout.addView(text);\r
-\r
- return layout;\r
- }\r
-\r
- @Override\r
- public void onSaveInstanceState(Bundle outState) {\r
- super.onSaveInstanceState(outState);\r
- outState.putString(KEY_CONTENT, mContent);\r
- }\r
-}\r
+++ /dev/null
-/*\r
- * Copyright (C) 2012 Evergreen Open-ILS\r
- * @author Daniel-Octavian Rizea\r
- * \r
- * This program is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU General Public License\r
- * as published by the Free Software Foundation; either version 2\r
- * or the License, or (at your option) any later version.\r
- * \r
- * This program is distributed in the hope that it will be usefull,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- * \r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software \r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\r
- * \r
- */\r
-package org.evergreen.android.utils.ui;\r
-\r
-import android.support.v4.app.Fragment;\r
-import android.support.v4.app.FragmentManager;\r
-import android.support.v4.app.FragmentPagerAdapter;\r
-\r
-public class TestFragmentAdapter extends FragmentPagerAdapter {\r
- protected static final String[] CONTENT = new String[] { "This", "Is", "A",\r
- "Test", };\r
-\r
- private int mCount = CONTENT.length;\r
-\r
- public TestFragmentAdapter(FragmentManager fm) {\r
- super(fm);\r
- }\r
-\r
- @Override\r
- public Fragment getItem(int position) {\r
- return TestFragment.newInstance(CONTENT[position % CONTENT.length]);\r
- }\r
-\r
- @Override\r
- public int getCount() {\r
- return mCount;\r
- }\r
-\r
-}
\ No newline at end of file
+++ /dev/null
-/*
- * 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<Rect> 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<Rect> calculateAllBounds(Paint paint) {
- ArrayList<Rect> list = new ArrayList<Rect>();
- // 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<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
- @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();
- }
-}
+++ /dev/null
-/*
- * 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<SavedState> CREATOR = new Creator<SavedState>() {
- @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
+++ /dev/null
-/*
- * 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));
-
- }
-
- }
-
-}
+++ /dev/null
-/*
- * 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);
- }
- }
- }
-
-}
+++ /dev/null
-/*
- * 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<String,String,String>, 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<Bundle> 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);
- }
-}
+++ /dev/null
-/*
- * 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:
- * <code>
- * if (!SplashActivity.isInitialized) {
- * SplashActivity.restartApp(this);
- * return;
- * }
- * </code>
- *
- * @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);
- }
- }
-}
--- /dev/null
+/*
+ * 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<BookBag> bookBags = new ArrayList<BookBag>();
+
+ /** 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<CircRecord> getItemsCheckedOut()
+ throws SessionNotFoundException {
+
+ ArrayList<CircRecord> circRecords = new ArrayList<CircRecord>();
+
+ Object resp = Utils.doRequest(conn, SERVICE_ACTOR,
+ METHOD_FETCH_CHECKED_OUT_SUM, authToken, new Object[] {
+ authToken, userID });
+ if (resp == null)
+ return circRecords;
+ Map<String, ?> resp_map = ((Map<String, ?>) resp);
+
+ if (resp_map.get("out") != null) {
+ List<String> out_id = (List<String>) 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<String> overdue_id = (List<String>) 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<CircRecord>() {
+ @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<String, Integer> complexParam = new HashMap<String, Integer>();
+ 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<String, String> resp = (Map<String, String>) 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<HoldRecord> getHolds() throws SessionNotFoundException {
+
+ ArrayList<HoldRecord> holds = new ArrayList<HoldRecord>();
+
+ // fields of interest : expire_time
+ List<OSRFObject> 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<OSRFObject>) 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<Object>) 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<Object>) 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<Object>) 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<String, Object> param = new HashMap<String, Object>();
+
+ param.put("cache", 1);
+
+ ArrayList<String> fieldsList = new ArrayList<String>();
+ fieldsList.add("label");
+ fieldsList.add("record");
+
+ param.put("fields", fieldsList);
+ HashMap<String, Integer> queryParam = new HashMap<String, Integer>();
+ // PART_ID use "target field in hold"
+ queryParam.put("id", hold.getInt("target"));
+ param.put("query", queryParam);
+
+ // returns [{record:id, label=part label}]
+
+ List<Object> part = (List<Object>) Utils.doRequest(conn,
+ SERVICE_FIELDER, "open-ils.fielder.bmp.atomic", cm,
+ new Object[] { param });
+
+ Map<String, ?> partObj = (Map<String, ?>) 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<Object>) 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<String, Integer> map = (Map<String, Integer>)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<String, String>) map).get("textcode");
+ resp[2] = ((Map<String, String>) 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<String, Integer> 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<String, Integer> getHoldPreCreateInfo(Integer recordID,
+ Integer pickup_lib) {
+
+ HashMap<String, Integer> param = new HashMap<String, Integer>();
+
+ param.put("pickup_lib", pickup_lib);
+ param.put("record", recordID);
+
+ Map<String, ?> response = (Map<String, ?>) 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<String, Integer> map = new HashMap<String, Integer>();
+ 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<FinesRecord> getTransactions()
+ throws SessionNotFoundException {
+
+ ArrayList<FinesRecord> finesRecords = new ArrayList<FinesRecord>();
+
+ Object transactions = Utils.doRequest(conn, SERVICE_ACTOR,
+ METHOD_FETCH_TRANSACTIONS, authToken, new Object[] {
+ authToken, userID });
+
+ // get Array
+
+ List<Map<String, OSRFObject>> list = (List<Map<String, OSRFObject>>) transactions;
+
+ for (int i = 0; i < list.size(); i++) {
+
+ Map<String, OSRFObject> 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<OSRFObject> bookbags = (List<OSRFObject>) response;
+
+ ArrayList<BookBag> bookBagObj = new ArrayList<BookBag>();
+ // 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<BookBag> 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<String, ?> map = (Map<String, ?>) Utils.doRequest(conn,
+ SERVICE_ACTOR, METHOD_FLESH_PUBLIC_CONTAINER, authToken,
+ new Object[] { authToken, "biblio", bookbagID });
+
+ List<OSRFObject> items = new ArrayList<OSRFObject>();
+
+ try{
+ items = (List<OSRFObject>) 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 });
+ }
+}
--- /dev/null
+/*
+ * 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;
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+
+}
--- /dev/null
+/*
+ * 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<BookBagItem> 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<BookBagItem>();
+
+ String pub_visible = object.getString("pub");
+
+ if (pub_visible.equals("f"))
+ this.shared = false;
+ else
+ this.shared = true;
+ }
+
+}
--- /dev/null
+/*
+ * 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<BookBagItem> 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<BookBagItem>();
+ 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<RecordInfo> records = new ArrayList<RecordInfo>();
+ ArrayList<Integer> ids = new ArrayList<Integer>();
+
+ 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<BookBagItem> {
+ private static final String tag = "BookbagArrayAdapter";
+
+ private TextView title;
+ private TextView author;
+ private Button remove;
+
+ private List<BookBagItem> records = new ArrayList<BookBagItem>();
+
+ public BookBagItemsArrayAdapter(Context context,
+ int textViewResourceId, List<BookBagItem> 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;
+ }
+ }
+}
--- /dev/null
+/*
+ * 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");
+
+ }
+}
--- /dev/null
+/*
+ * 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<BookBag> 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<BookBag>();
+ 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<BookBag> {
+ private static final String tag = "BookbagArrayAdapter";
+
+ private TextView name;
+ private TextView items;
+ private CheckBox shared;
+ private Button detailsButton;
+
+ private List<BookBag> records = new ArrayList<BookBag>();
+
+ public BookBagsArrayAdapter(Context context, int textViewResourceId,
+ List<BookBag> 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;
+ }
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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<CircRecord> 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<CircRecord>();
+ 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<CircRecord> {
+ private static final String tag = "CheckoutArrayAdapter";
+
+ private TextView recordTitle;
+ private TextView recordAuthor;
+ private TextView recordDueDate;
+ private TextView recordRenewals;
+ private TextView renewButton;
+
+ private List<CircRecord> records = new ArrayList<CircRecord>();
+
+ public CheckOutArrayAdapter(Context context, int textViewResourceId,
+ List<CircRecord> 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;
+ }
+ }
+}
--- /dev/null
+/*
+ * 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<FinesRecord> finesRecords = new ArrayList<FinesRecord>();
+ 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<FinesRecord> frecords = null;
+ try {
+ frecords = ac.getTransactions();
+ } catch (SessionNotFoundException e) {
+ try {
+ if (ac.reauthenticate(FinesActivity.this))
+ frecords = ac.getTransactions();
+ } catch (Exception e1) {
+ }
+ }
+
+ final ArrayList<FinesRecord> 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<FinesRecord> {
+ private static final String tag = "CheckoutArrayAdapter";
+
+ private TextView fineTitle;
+ private TextView fineAuthor;
+ private TextView fineBalanceOwed;
+ private TextView fineStatus;
+
+ private List<FinesRecord> records = new ArrayList<FinesRecord>();
+
+ public OverdueMaterialsArrayAdapter(Context context,
+ int textViewResourceId, List<FinesRecord> 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;
+ }
+ }
+}
--- /dev/null
+/*
+ * 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";
+
+ }
+}
--- /dev/null
+/*
+ * 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<String> list = new ArrayList<String>();
+ 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<String> adapter = new ArrayAdapter<String>(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));
+ }
+
+}
--- /dev/null
+/*
+ * 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 "";
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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<HoldRecord> 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<HoldRecord>();
+ 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<HoldRecord> {
+ private static final String tag = "CheckoutArrayAdapter";
+
+ private TextView holdTitle;
+ private TextView holdAuthor;
+ private TextView status;
+ private ImageView hold_icon;
+
+ private List<HoldRecord> records = new ArrayList<HoldRecord>();
+
+ public HoldsArrayAdapter(Context context, int textViewResourceId,
+ List<HoldRecord> 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;
+ }
+ }
+}
--- /dev/null
+/*
+ * 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<String> list = new ArrayList<String>();
+ 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<String> adapter = new ArrayAdapter<String>(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));
+ }
+
+}
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;
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";
--- /dev/null
+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<BarcodeFormat> 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();
+ }
+
+}
--- /dev/null
+
+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<BarcodeFormat> 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();
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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<BarcodeFormat> PRODUCT_FORMATS;
+ static final Vector<BarcodeFormat> ONE_D_FORMATS;
+ static final Vector<BarcodeFormat> QR_CODE_FORMATS;
+ static final Vector<BarcodeFormat> DATA_MATRIX_FORMATS;
+ static {
+ PRODUCT_FORMATS = new Vector<BarcodeFormat>(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<BarcodeFormat>(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<BarcodeFormat>(1);
+ QR_CODE_FORMATS.add(BarcodeFormat.QR_CODE);
+ DATA_MATRIX_FORMATS = new Vector<BarcodeFormat>(1);
+ DATA_MATRIX_FORMATS.add(BarcodeFormat.DATA_MATRIX);
+ }
+
+ private DecodeFormatManager() {}
+
+ static Vector<BarcodeFormat> parseDecodeFormats(Intent intent) {
+ List<String> 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<BarcodeFormat> parseDecodeFormats(Uri inputUri) {
+ List<String> 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<BarcodeFormat> parseDecodeFormats(Iterable<String> scanFormats,
+ String decodeMode) {
+ if (scanFormats != null) {
+ Vector<BarcodeFormat> formats = new Vector<BarcodeFormat>();
+ 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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<DecodeHintType, Object> 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();
+ }
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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<DecodeHintType, Object> hints;
+ private Handler handler;
+ private final CountDownLatch handlerInitLatch;
+ private CameraManager cameraManager;
+ DecodeThread(CaptureActivity activity,
+ Vector<BarcodeFormat> decodeFormats,
+ String characterSet,
+ ResultPointCallback resultPointCallback, CameraManager cameraManager) {
+
+ this.activity = activity;
+ handlerInitLatch = new CountDownLatch(1);
+ this.cameraManager = cameraManager;
+ hints = new Hashtable<DecodeHintType, Object>(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<BarcodeFormat>();
+ 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();
+ }
+
+}
--- /dev/null
+/*
+ * 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();
+ }
+
+}
--- /dev/null
+package org.evergreen_ils.barcodescan;\r
+\r
+import android.content.Context;\r
+import android.graphics.Color;\r
+import android.widget.TextView;\r
+import android.widget.Toast;\r
+\r
+/**\r
+ * \r
+ * @author George Oprina\r
+ * \r
+ * 08.06.2011\r
+ */\r
+\r
+public class Functions {\r
+\r
+ // makes toast length short\r
+ public static void makeToast(String s, Context c) {\r
+ CharSequence text = s;\r
+ int duration = Toast.LENGTH_SHORT;\r
+\r
+ Toast toast = Toast.makeText(c, text, duration);\r
+ toast.show();\r
+ }\r
+\r
+ // makes toast selectable length\r
+ public static void makeToast(String s, Context c, int length) {\r
+ CharSequence text = s;\r
+ int duration = Toast.LENGTH_SHORT;\r
+\r
+ if (length == 1)\r
+ duration = Toast.LENGTH_LONG;\r
+\r
+ Toast toast = Toast.makeText(c, text, duration);\r
+ toast.show();\r
+ }\r
+\r
+ // makes text view from string\r
+ public static TextView makeTextView(String s, Context c) {\r
+ TextView text = new TextView(c);\r
+ text.setBackgroundColor(Color.WHITE);\r
+ text.setText(s);\r
+ text.setTextColor(Color.BLACK);\r
+ return text;\r
+ }\r
+\r
+ // thread sleep\r
+ public static void sleep(int msec) {\r
+ try {\r
+ Thread.sleep(msec);\r
+ } catch (InterruptedException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+/*
+ * 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() {
+ }
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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<CheckBoxPreference> checked = new ArrayList<CheckBoxPreference>(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)));
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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);
+ }
+
+}
--- /dev/null
+/*
+ * 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<ResultPoint> possibleResultPoints;
+ private List<ResultPoint> 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<ResultPoint>(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<ResultPoint> currentPossible = possibleResultPoints;
+ List<ResultPoint> currentLast = lastPossibleResultPoints;
+ int frameLeft = frame.left;
+ int frameTop = frame.top;
+ if (currentPossible.isEmpty()) {
+ lastPossibleResultPoints = null;
+ } else {
+ possibleResultPoints = new ArrayList<ResultPoint>(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<ResultPoint> 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();
+ }
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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");
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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<String> 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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);
+ }
+
+}
--- /dev/null
+/*
+ * 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);
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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");
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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", "");
+ }
+}
--- /dev/null
+/*
+ * 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<Class, ReflectionManager> rmMap = new HashMap<Class, ReflectionManager>();
+
+ @SuppressWarnings("rawtypes")
+ private static HashMap<Class, DefaultDAO> daoMap = new HashMap<Class, DefaultDAO>();
+
+ /**
+ * 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 <T> ReflectionManager getReflectionManagerInstance(
+ Class<T> 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 <T>
+ * the generic type
+ * @param cls
+ * the class
+ * @param tableName
+ * the table name
+ * @return the DAO instance
+ */
+ @SuppressWarnings("unchecked")
+ public static synchronized <T> DefaultDAO<T> getDAOInstance(
+ Context context, Class<T> cls, String tableName) {
+ if (daoMap.containsKey(cls))
+ return daoMap.get(cls);
+ DefaultDAO<T> dao = new DefaultDAO<T>(cls,
+ DatabaseManager.getDBHelper(context),
+ DatabaseManager.getReflectionManagerInstance(cls), tableName);
+ daoMap.put(cls, dao);
+ return dao;
+ }
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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<Organisation> 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<Organisation>();
+
+ 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<Organisation>();
+
+ // 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<orgList.size(); ++i) {
+ Organisation org = new Organisation();
+ List orgItem = (List) orgList.get(i);
+ org.id= (Integer)orgItem.get(0);
+ org.level = (Integer)orgItem.get(1);
+ org.parent = (Integer)orgItem.get(2);
+ org.name = (String)orgItem.get(3);
+ org.isVisible = (Integer)orgItem.get(4);
+ org.shortName = (String)orgItem.get(5);
+ if (org.isVisible == 0) {
+ continue;
+ }
+
+ organisations.add(org);
+ }
+
+ /*
+ for (int i=0; i<organisations.size(); ++i) {
+ Log.d(TAG, "getOrg presort org["+i+"]= id:"+organisations.get(i).id+" parent:"+organisations.get(i).parent+" name:"+organisations.get(i).name);
+ }
+ */
+ Collections.sort(organisations, new Comparator<Organisation>() {
+ @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<organisations.size(); ++i) {
+ Log.d(TAG, "getOrg postsort org["+i+"]= id:"+organisations.get(i).id+" parent:"+organisations.get(i).parent+" name:"+organisations.get(i).name);
+ }
+ */
+
+ long duration_ms = System.currentTimeMillis() - start_ms;
+ Log.d("init", "Loading organisations took "+duration_ms+"ms");
+ loadedOrgTree = true;
+ }
+ }
+
+ public void getCopyStatusesAvailable(ConnectivityManager cm) {
+
+ SearchCatalog search = SearchCatalog.getInstance(cm);
+
+ try {
+ search.getCopyStatuses();
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ public void getOrgHiddentDepth() {
+
+ // logic can be found in the opac_utils.js file in web/opac/common/js
+
+ for (int i = 0; i < organisations.size(); i++) {
+ AccountAccess ac = AccountAccess.getAccountAccess();
+ try {
+ Object obj = ac.fetchOrgSettings(organisations.get(i).id,
+ "opac.org_unit_hiding.depth");
+ } catch (SessionNotFoundException e) {
+ }
+
+ }
+
+ }
+
+ public static String getStringDate(Date date) {
+
+ final SimpleDateFormat sdf = new SimpleDateFormat(
+ GlobalConfigs.datePattern);
+
+ return sdf.format(date);
+
+ }
+
+ // parse from opac methods query results to Java date
+ public static Date parseDate(String dateString) {
+
+ if (dateString == null)
+ return null;
+
+ Date date = null;
+ final SimpleDateFormat sdf = new SimpleDateFormat(
+ GlobalConfigs.datePattern);
+
+ try {
+ date = sdf.parse(dateString);
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+
+ return date;
+ }
+
+ // parse from opac methods query result to boolean
+ public static boolean parseBoolean(String boolString) {
+ return (boolString != null && boolString.equals("t"));
+ }
+
+ public String getOrganizationName(int id) {
+
+ for (int i = 0; i < organisations.size(); i++) {
+ if (organisations.get(i).id == id)
+ return organisations.get(i).name;
+ }
+
+ return null;
+ }
+}
--- /dev/null
+/*
+ * 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.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+
+public class ShowServerNotAvailableRunnable implements Runnable {
+
+ private Context context;
+
+ public ShowServerNotAvailableRunnable(Context context) {
+ this.context = context;
+ }
+
+ @Override
+ public void run() {
+ AlertDialog alertDialog = new AlertDialog.Builder(context).create();
+ alertDialog.setTitle("Error");
+ alertDialog.setMessage("There is no network connectivity to "
+ + GlobalConfigs.httpAddress);
+ alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ dialog.dismiss();
+ }
+ });
+
+ alertDialog.show();
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+
+class ShowSessionNotAvailableRunnable implements Runnable {
+
+ public Context context;
+
+ public ShowSessionNotAvailableRunnable(Context context) {
+ this.context = context;
+ }
+
+ @Override
+ public void run() {
+ AlertDialog alertDialog = new AlertDialog.Builder(context).create();
+ alertDialog.setTitle("Error");
+ alertDialog.setMessage("No session");
+ alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ dialog.dismiss();
+ }
+ });
+
+ alertDialog.show();
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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 java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Map;
+
+import android.os.Looper;
+import android.text.TextUtils;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.evergreen_ils.accountAccess.SessionNotFoundException;
+import org.opensrf.Method;
+import org.opensrf.net.http.GatewayRequest;
+import org.opensrf.net.http.HttpConnection;
+import org.opensrf.net.http.HttpRequest;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.ConnectivityManager;
+import android.util.Log;
+import android.widget.ImageView;
+
+public class Utils {
+ private static final String TAG = "osrf";
+
+ /**
+ * Gets the net page content.
+ *
+ * @param url
+ * the url of the page to be retrieved
+ * @return the net page content
+ */
+ public static String getNetPageContent(String url) {
+
+ String result = "";
+
+ HttpResponse response = null;
+
+ try {
+ HttpClient client = new DefaultHttpClient();
+ HttpGet request = new HttpGet(url);
+ response = client.execute(request);
+ } catch (Exception e) {
+ Log.d(TAG, "Exception to GET page " + url);
+ }
+ StringBuilder str = null;
+
+ try {
+ InputStream in = response.getEntity().getContent();
+ BufferedReader reader = new BufferedReader(
+ new InputStreamReader(in));
+ str = new StringBuilder();
+ String line = null;
+ while ((line = reader.readLine()) != null) {
+ str.append(line);
+ }
+ in.close();
+ } catch (Exception e) {
+ System.err
+ .println("Error in retrieving response " + e.getMessage());
+ }
+
+ result = str.toString();
+
+ return result;
+ }
+
+ public static InputStream getNetInputStream(String url) {
+
+ InputStream in = null;
+
+ HttpResponse response = null;
+
+ try {
+ HttpClient client = new DefaultHttpClient();
+ HttpGet request = new HttpGet(url);
+ response = client.execute(request);
+ } catch (Exception e) {
+ Log.d(TAG, "Exception to GET page " + url);
+ }
+
+ try {
+ in = response.getEntity().getContent();
+
+ return in;
+ } catch (Exception e) {
+ System.err
+ .println("Error in retrieving response " + e.getMessage());
+ }
+
+ return in;
+ }
+
+ public static boolean checkIfNetAddressIsReachable(String url) {
+
+ // The old method of fetching the URL to see if the net is "reachable" was not good;
+ // it wasted bandwidth and time. For now just check if the url is empty.
+ return (url.length() > 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<String, String>) 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);
+ }
+
+}
--- /dev/null
+/*
+ * 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();
+ }
+ });
+
+ }
+
+}
--- /dev/null
+/*
+ * 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<String, Integer>) map).get("org_unit");
+ this.count = ((Map<String, Integer>) map).get("count");
+ this.available = ((Map<String, Integer>) map).get("available");
+ this.depth = ((Map<String, Integer>) map).get("depth");
+ this.unshadow = ((Map<String, Integer>) map).get("unshadow");
+
+ Log.d(TAG, org_id + " " + available + " " + count);
+ }
+
+}
--- /dev/null
+/*
+ * 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<String, String> statuses;
+
+ // the hash from the request method
+ private HashMap<Integer, Integer> hashValCopy;
+
+ // global, it is initialized when orgTree and fm_ild is downloaded
+
+ public static LinkedHashMap<String, String> availableOrgStatuses;
+
+ public LinkedHashMap<String, String> statusInformation = null;
+
+ public CopyInformation(List<Object> list) {
+
+ org_id = Integer.parseInt((String) list.get(0));
+ call_number_sufix = (String) list.get(2);
+ copy_location = (String) list.get(4);
+
+ hashValCopy = (HashMap<Integer, Integer>) list.get(5);
+
+ statusInformation = new LinkedHashMap<String, String>();
+
+ Set<Entry<String, String>> set = availableOrgStatuses.entrySet();
+
+ Iterator<Entry<String, String>> it = set.iterator();
+
+ while (it.hasNext()) {
+ Entry<String, String> 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()));
+ }
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.
+ *
+ * <p>
+ * It requires the INTERNET permission, which should be added to your
+ * application's manifest file.
+ * </p>
+ *
+ * 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<String, Void, Bitmap> {
+ private String url;
+ private final WeakReference<ImageView> imageViewReference;
+
+ public BitmapDownloaderTask(ImageView imageView) {
+ imageViewReference = new WeakReference<ImageView>(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.
+ *
+ * <p>
+ * 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.
+ * </p>
+ */
+ static class DownloadedDrawable extends ColorDrawable {
+ private final WeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference;
+
+ public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) {
+ super(Color.BLACK);
+
+ bitmapDownloaderTaskReference = new WeakReference<BitmapDownloaderTask>(
+ 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<String, Bitmap> sHardBitmapCache = new LinkedHashMap<String, Bitmap>(
+ HARD_CACHE_CAPACITY / 2, 0.75f, true) {
+ @Override
+ protected boolean removeEldestEntry(
+ LinkedHashMap.Entry<String, Bitmap> 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<Bitmap>(eldest.getValue()));
+ return true;
+ } else
+ return false;
+ }
+ };
+
+ // Soft cache for bitmaps kicked out of hard cache
+ private final static ConcurrentHashMap<String, SoftReference<Bitmap>> sSoftBitmapCache = new ConcurrentHashMap<String, SoftReference<Bitmap>>(
+ 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<Bitmap> 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);
+ }
+}
--- /dev/null
+/*
+ * 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<Entry<String, String>> set = info.statusInformation.entrySet();
+
+ Iterator<Entry<String, String>> it = set.iterator();
+
+ while (it.hasNext()) {
+
+ Entry<String, String> 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));
+
+ }
+
+ }
+
+ }
+}
--- /dev/null
+/*
+ * 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() {
+
+ }
+}
--- /dev/null
+/*
+ * 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<CopyCountInformation> copyCountListInfo = null;
+
+ public List<CopyInformation> copyInformationList = null;
+
+ public RecordInfo() {
+ this.title = "Test title";
+ this.author = "Test author";
+ this.pubdate = "Publication date";
+ copyInformationList = new ArrayList<CopyInformation>();
+
+ // marks the fact that this is a record made from no info
+ this.dummy = true;
+ }
+
+ public RecordInfo(OSRFObject info) {
+ copyInformationList = new ArrayList<CopyInformation>();
+ 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<String, ?> subjectMap = (Map<String, ?>) info.get("subject");
+
+ this.subject = "";
+
+ int no = subjectMap.entrySet().size();
+ int i = 0;
+ for (Entry<String, ?> 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<String> 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());
+ }
+ ;
+
+ }
+}
--- /dev/null
+/*
+ * 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<RecordInfo> records;
+
+ private Button myAccountButton;
+
+ private Button homeButton;
+
+ private TextView headerTitle;
+
+ private SearchCatalog search;
+
+ private ArrayList<RecordInfo> 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<RecordInfo>) 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
--- /dev/null
+/*
+ * 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<RecordInfo> getSearchResults(String searchWords,
+ Integer offset) {
+
+ searchText = searchWords;
+
+ ArrayList<RecordInfo> resultsRecordInfo = new ArrayList<RecordInfo>();
+
+ Method method = new Method(METHOD_MULTICLASS_QUERY);
+
+ HashMap complexParm = new HashMap<String, Integer>();
+
+ 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<String> ids = new ArrayList<String>();
+
+ Log.d(TAG, "Sync Response: " + resp);
+ if (resp == null)
+ return resultsRecordInfo; // search failed or server crashed
+
+ Map<String, ?> response = (Map<String, ?>) resp;
+
+ Log.d(TAG, " ids : " + response.get("ids") + " ");
+
+ List<List<String>> result_ids;
+ result_ids = (List<List<String>>) 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<Object>> list = (List<List<Object>>) 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<OSRFObject> ccs_list = (List<OSRFObject>) Utils.doRequestSimple(
+ conn, SERVICE, METHOD_COPY_STATUS_ALL, new Object[] {});
+
+ CopyInformation.availableOrgStatuses = new LinkedHashMap<String, String>();
+
+ 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<RecordInfo> getRecordsInfo(ArrayList<Integer> ids) {
+
+ ArrayList<RecordInfo> recordInfoArray = new ArrayList<RecordInfo>();
+
+ 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<CopyCountInformation> getCopyCount(Integer recordID,
+ Integer orgID) {
+
+ List<?> list = (List<?>) Utils.doRequestSimple(conn, SERVICE,
+ METHOD_GET_COPY_COUNT, new Object[] { orgID, recordID, "" });
+
+ ArrayList<CopyCountInformation> copyInfoList = new ArrayList<CopyCountInformation>();
+
+ 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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<RecordInfo> recordList;
+
+ private EditText searchText;
+
+ private ImageButton searchButton;
+
+ private SearchCatalog search;
+
+ private ListView lv;
+
+ private SearchArrayAdapter adapter;
+
+ private Context context;
+
+ private ProgressDialog progressDialog;
+
+ private ArrayList<RecordInfo> 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<BookBag> 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<RecordInfo>();
+
+ // 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<RecordInfo>();
+
+ 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<String> list = new ArrayList<String>();
+ 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<String> adapter = new ArrayAdapter<String>(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<RecordInfo> records = (ArrayList)data.getSerializableExtra("recordList");
+
+ recordList.clear();
+ for(int i=0;i<records.size();i++){
+ recordList.add(records.get(i));
+ }
+ adapter.notifyDataSetChanged();
+
+ searchResultsNumber.setText(adapter
+ .getCount()
+ + " out of "
+ + search.visible);
+ }
+ break;
+
+ case AdvancedSearchActivity.RESULT_ADVANCED_SEARCH: {
+ Log.d(TAG,
+ "result text" + data.getStringExtra("advancedSearchText"));
+ searchText.setText(data.getStringExtra("advancedSearchText"));
+ Thread searchThread = new Thread(searchForResultsRunnable);
+ searchThread.start();
+ }
+ break;
+
+ case CaptureActivity.BARCODE_SEARCH: {
+ searchText.setText("identifier|isbn: "
+ + data.getStringExtra("barcodeValue"));
+ Thread searchThread = new Thread(searchForResultsRunnable);
+ searchThread.start();
+ }
+
+ }
+ }
+
+ class SearchArrayAdapter extends ArrayAdapter<RecordInfo> {
+
+ private static final String tag = "SearchArrayAdapter";
+ private Context context;
+ private ImageView recordImage;
+ private TextView recordTitle;
+ private TextView recordAuthor;
+ private TextView recordPublisher;
+
+ private List<RecordInfo> records = new ArrayList<RecordInfo>();
+
+ public SearchArrayAdapter(Context context, int textViewResourceId,
+ List<RecordInfo> 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;
+ }
+ }
+}
--- /dev/null
+/*
+ * 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
+ + "]";
+ }
+}
--- /dev/null
+/*
+ * 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);
+
+ }
+
+}
--- /dev/null
+/*
+ * 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);
+ }
+ }
+
+ }
+
+ }
+
+}
--- /dev/null
+/*
+ * 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);
+ }
+
+ }
+
+}
--- /dev/null
+/*
+ * 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<Bundle> 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<CircRecord> circRecords = new ArrayList<CircRecord>();
+
+ // get the circ records
+ try {
+ circRecords = accountAccess.getItemsCheckedOut();
+ } catch (SessionNotFoundException e) {
+ // auth just earlier realized, not supose to happen
+ }
+
+ DefaultDAO<NotificationAlert> daoNotifications = DatabaseManager
+ .getDAOInstance(this, NotificationAlert.class,
+ NotificationAlert.tableName);
+ daoNotifications.open();
+
+ // Fetch all alarms from database
+ List<NotificationAlert> 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);
+ }
+ */
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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<BookBag> 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<Entry<String, String>> set = info.statusInformation.entrySet();
+
+ Iterator<Entry<String, String>> it = set.iterator();
+
+ while (it.hasNext()) {
+
+ Entry<String, String> 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));
+
+ }
+
+ }
+
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+ }
+}
--- /dev/null
+/*
+ * 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);
+
+ /**
+ * <p>
+ * Set the current page of both the ViewPager and indicator.
+ * </p>
+ *
+ * <p>
+ * This <strong>must</strong> be used if you need to set the page before the
+ * views are drawn on screen (e.g., default start page).
+ * </p>
+ *
+ * @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();
+}
--- /dev/null
+/*
+ * 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;
+ }
+ }
+}
--- /dev/null
+/*\r
+ * Copyright (C) 2012 Evergreen Open-ILS\r
+ * @author Daniel-Octavian Rizea\r
+ * \r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * or the License, or (at your option) any later version.\r
+ * \r
+ * This program is distributed in the hope that it will be usefull,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ * \r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software \r
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\r
+ * \r
+ */\r
+package org.evergreen_ils.utils.ui;\r
+\r
+import android.os.Bundle;\r
+import android.support.v4.app.Fragment;\r
+import android.view.Gravity;\r
+import android.view.LayoutInflater;\r
+import android.view.View;\r
+import android.view.ViewGroup;\r
+import android.widget.LinearLayout;\r
+import android.widget.LinearLayout.LayoutParams;\r
+import android.widget.TextView;\r
+\r
+public final class TestFragment extends Fragment {\r
+ private static final String KEY_CONTENT = "TestFragment:Content";\r
+\r
+ public static TestFragment newInstance(String content) {\r
+ TestFragment fragment = new TestFragment();\r
+\r
+ StringBuilder builder = new StringBuilder();\r
+ for (int i = 0; i < 20; i++) {\r
+ builder.append(content).append(" ");\r
+ }\r
+ builder.deleteCharAt(builder.length() - 1);\r
+ fragment.mContent = builder.toString();\r
+\r
+ return fragment;\r
+ }\r
+\r
+ private String mContent = "???";\r
+\r
+ @Override\r
+ public void onCreate(Bundle savedInstanceState) {\r
+ super.onCreate(savedInstanceState);\r
+\r
+ if ((savedInstanceState != null)\r
+ && savedInstanceState.containsKey(KEY_CONTENT)) {\r
+ mContent = savedInstanceState.getString(KEY_CONTENT);\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,\r
+ Bundle savedInstanceState) {\r
+ TextView text = new TextView(getActivity());\r
+ text.setGravity(Gravity.CENTER);\r
+ text.setText(mContent);\r
+ text.setTextSize(20 * getResources().getDisplayMetrics().density);\r
+ text.setPadding(20, 20, 20, 20);\r
+\r
+ LinearLayout layout = new LinearLayout(getActivity());\r
+ layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,\r
+ LayoutParams.MATCH_PARENT));\r
+ layout.setGravity(Gravity.CENTER);\r
+ layout.addView(text);\r
+\r
+ return layout;\r
+ }\r
+\r
+ @Override\r
+ public void onSaveInstanceState(Bundle outState) {\r
+ super.onSaveInstanceState(outState);\r
+ outState.putString(KEY_CONTENT, mContent);\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2012 Evergreen Open-ILS\r
+ * @author Daniel-Octavian Rizea\r
+ * \r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * or the License, or (at your option) any later version.\r
+ * \r
+ * This program is distributed in the hope that it will be usefull,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ * \r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software \r
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\r
+ * \r
+ */\r
+package org.evergreen_ils.utils.ui;\r
+\r
+import android.support.v4.app.Fragment;\r
+import android.support.v4.app.FragmentManager;\r
+import android.support.v4.app.FragmentPagerAdapter;\r
+\r
+public class TestFragmentAdapter extends FragmentPagerAdapter {\r
+ protected static final String[] CONTENT = new String[] { "This", "Is", "A",\r
+ "Test", };\r
+\r
+ private int mCount = CONTENT.length;\r
+\r
+ public TestFragmentAdapter(FragmentManager fm) {\r
+ super(fm);\r
+ }\r
+\r
+ @Override\r
+ public Fragment getItem(int position) {\r
+ return TestFragment.newInstance(CONTENT[position % CONTENT.length]);\r
+ }\r
+\r
+ @Override\r
+ public int getCount() {\r
+ return mCount;\r
+ }\r
+\r
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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<Rect> 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<Rect> calculateAllBounds(Paint paint) {
+ ArrayList<Rect> list = new ArrayList<Rect>();
+ // 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<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
+ @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();
+ }
+}
--- /dev/null
+/*
+ * 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<SavedState> CREATOR = new Creator<SavedState>() {
+ @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
--- /dev/null
+/*
+ * 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));
+
+ }
+
+ }
+
+}
--- /dev/null
+/*
+ * 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);
+ }
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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<String,String,String>, 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<Bundle> 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);
+ }
+}
--- /dev/null
+/*
+ * 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:
+ * <code>
+ * if (!SplashActivity.isInitialized) {
+ * SplashActivity.restartApp(this);
+ * return;
+ * }
+ * </code>
+ *
+ * @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);
+ }
+ }
+}
<!-- Notification receiver -->
<receiver
- android:name="org.evergreen.android.services.NotificationReceiver"
+ android:name="org.evergreen_ils.services.NotificationReceiver"
android:process=":remote" >
</receiver>
<!-- Receiver to reinit notifications on reboot -->
- <receiver android:name="org.evergreen.android.services.RebootReceiver" >
+ <receiver android:name="org.evergreen_ils.services.RebootReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
- <receiver android:name="org.evergreen.android.services.PeriodicServiceBroadcastReceiver" >
+ <receiver android:name="org.evergreen_ils.services.PeriodicServiceBroadcastReceiver" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
- <service android:name="org.evergreen.android.services.ScheduledIntentService" >
+ <service android:name="org.evergreen_ils.services.ScheduledIntentService" >
</service>
- <activity android:name="org.evergreen.android.views.splashscreen.SplashActivity">
+ <activity android:name="org.evergreen_ils.views.splashscreen.SplashActivity">
<!-- android:theme="@android:style/Theme.Light.NoTitleBar" -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
<activity
- android:name="org.evergreen.android.views.AccountScreenDashboard"
+ android:name="org.evergreen_ils.views.AccountScreenDashboard"
android:theme="@android:style/Theme.Light.NoTitleBar" >
</activity>
- <activity android:name="org.evergreen.android.views.ApplicationPreferences" >
+ <activity android:name="org.evergreen_ils.views.ApplicationPreferences" >
</activity>
<!-- Search -->
<activity
- android:name="org.evergreen.android.searchCatalog.SampleUnderlinesNoFade"
+ android:name="org.evergreen_ils.searchCatalog.SampleUnderlinesNoFade"
android:label="Underlines/No Fade" >
</activity>
- <activity android:name="org.evergreen.android.searchCatalog.MoreCopyInformation" >
+ <activity android:name="org.evergreen_ils.searchCatalog.MoreCopyInformation" >
</activity>
- <activity android:name="org.evergreen.android.searchCatalog.SearchCatalogListView">
+ <activity android:name="org.evergreen_ils.searchCatalog.SearchCatalogListView">
</activity>
- <activity android:name="org.evergreen.android.searchCatalog.AdvancedSearchActivity" >
+ <activity android:name="org.evergreen_ils.searchCatalog.AdvancedSearchActivity" >
</activity>
<activity
- android:name="org.evergreen.android.barcodescan.CaptureActivity"
+ android:name="org.evergreen_ils.barcodescan.CaptureActivity"
android:screenOrientation="landscape"
android:theme="@android:style/Theme.NoTitleBar"
android:windowSoftInputMode="stateAlwaysHidden" >
</activity>
<!-- Checkout Activities -->
- <activity android:name="org.evergreen.android.accountAccess.checkout.ItemsCheckOutListView" >
+ <activity android:name="org.evergreen_ils.accountAccess.checkout.ItemsCheckOutListView" >
</activity>
<!-- Holds Activities -->
- <activity android:name="org.evergreen.android.accountAccess.holds.HoldsListView" >
+ <activity android:name="org.evergreen_ils.accountAccess.holds.HoldsListView" >
</activity>
- <activity android:name="org.evergreen.android.accountAccess.holds.PlaceHold" >
+ <activity android:name="org.evergreen_ils.accountAccess.holds.PlaceHold" >
</activity>
- <activity android:name="org.evergreen.android.accountAccess.holds.HoldDetails" >
+ <activity android:name="org.evergreen_ils.accountAccess.holds.HoldDetails" >
</activity>
<!-- Fines Activities -->
- <activity android:name="org.evergreen.android.accountAccess.fines.FinesActivity" >
+ <activity android:name="org.evergreen_ils.accountAccess.fines.FinesActivity" >
</activity>
<!-- Bookbags -->
- <activity android:name="org.evergreen.android.accountAccess.bookbags.BookbagsListView" >
+ <activity android:name="org.evergreen_ils.accountAccess.bookbags.BookbagsListView" >
</activity>
- <activity android:name="org.evergreen.android.accountAccess.bookbags.BookBagDetails" >
+ <activity android:name="org.evergreen_ils.accountAccess.bookbags.BookBagDetails" >
</activity>
<activity
<!-- Notification receiver -->
<receiver
- android:name="org.evergreen.android.services.NotificationReceiver"
+ android:name="org.evergreen_ils.services.NotificationReceiver"
android:process=":remote">
</receiver>
<!-- Receiver to reinit notifications on reboot -->
- <receiver android:name="org.evergreen.android.services.RebootReceiver">
+ <receiver android:name="org.evergreen_ils.services.RebootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
- <receiver android:name="org.evergreen.android.services.PeriodicServiceBroadcastReceiver">
+ <receiver android:name="org.evergreen_ils.services.PeriodicServiceBroadcastReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
</intent-filter>
</receiver>
- <service android:name="org.evergreen.android.services.ScheduledIntentService">
+ <service android:name="org.evergreen_ils.services.ScheduledIntentService">
</service>
- <activity android:name="org.evergreen.android.views.splashscreen.SplashActivity">
+ <activity android:name="org.evergreen_ils.views.splashscreen.SplashActivity">
<!-- android:theme="@android:style/Theme.Light.NoTitleBar" -->
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
</intent-filter>
</activity>
<activity
- android:name="org.evergreen.android.views.AccountScreenDashboard"
+ android:name="org.evergreen_ils.views.AccountScreenDashboard"
android:theme="@android:style/Theme.Light.NoTitleBar">
</activity>
- <activity android:name="org.evergreen.android.views.ApplicationPreferences">
+ <activity android:name="org.evergreen_ils.views.ApplicationPreferences">
</activity>
<!-- Search -->
<activity
- android:name="org.evergreen.android.searchCatalog.SampleUnderlinesNoFade"
+ android:name="org.evergreen_ils.searchCatalog.SampleUnderlinesNoFade"
android:label="Underlines/No Fade">
</activity>
- <activity android:name="org.evergreen.android.searchCatalog.MoreCopyInformation">
+ <activity android:name="org.evergreen_ils.searchCatalog.MoreCopyInformation">
</activity>
- <activity android:name="org.evergreen.android.searchCatalog.SearchCatalogListView">
+ <activity android:name="org.evergreen_ils.searchCatalog.SearchCatalogListView">
</activity>
- <activity android:name="org.evergreen.android.searchCatalog.AdvancedSearchActivity">
+ <activity android:name="org.evergreen_ils.searchCatalog.AdvancedSearchActivity">
</activity>
<activity
- android:name="org.evergreen.android.barcodescan.CaptureActivity"
+ android:name="org.evergreen_ils.barcodescan.CaptureActivity"
android:screenOrientation="landscape"
android:theme="@android:style/Theme.NoTitleBar"
android:windowSoftInputMode="stateAlwaysHidden">
</activity>
<!-- Checkout Activities -->
- <activity android:name="org.evergreen.android.accountAccess.checkout.ItemsCheckOutListView">
+ <activity android:name="org.evergreen_ils.accountAccess.checkout.ItemsCheckOutListView">
</activity>
<!-- Holds Activities -->
- <activity android:name="org.evergreen.android.accountAccess.holds.HoldsListView">
+ <activity android:name="org.evergreen_ils.accountAccess.holds.HoldsListView">
</activity>
- <activity android:name="org.evergreen.android.accountAccess.holds.PlaceHold">
+ <activity android:name="org.evergreen_ils.accountAccess.holds.PlaceHold">
</activity>
- <activity android:name="org.evergreen.android.accountAccess.holds.HoldDetails">
+ <activity android:name="org.evergreen_ils.accountAccess.holds.HoldDetails">
</activity>
<!-- Fines Activities -->
- <activity android:name="org.evergreen.android.accountAccess.fines.FinesActivity">
+ <activity android:name="org.evergreen_ils.accountAccess.fines.FinesActivity">
</activity>
<!-- Bookbags -->
- <activity android:name="org.evergreen.android.accountAccess.bookbags.BookbagsListView">
+ <activity android:name="org.evergreen_ils.accountAccess.bookbags.BookbagsListView">
</activity>
- <activity android:name="org.evergreen.android.accountAccess.bookbags.BookBagDetails">
+ <activity android:name="org.evergreen_ils.accountAccess.bookbags.BookBagDetails">
</activity>
<activity