Commit 41704e56 authored by Varun Patil's avatar Varun Patil

Add InstiMAP

parent f9393d50
[{"id":"1","name":"Advanced Centre for Research in Electronics","short_name":"ACRE","group_id":"1","pixel_x":"4081","pixel_y":"1344","parent_id":"20","parent_rel":"Inside","description":"","lat":"0","long":"0","child_ids":[]},{"id":"2","name":"Aerospace Engineering Department","short_name":"Aero engg","group_id":"1","pixel_x":"4153","pixel_y":"2249","parent_id":"0","parent_rel":"","description":"http:\/\/www.aero.iitb.ac.in\/\nPhone No.: +912225767101 \/ +912225767102\nFax No.: +91222572 2602.\nEmail: office@aero.iitb.ac.in \nThe department offers academic programs for B. Tech, M. Tech, Ph. D. Specialization are offered: Aerodynamics, Control and Guidance, Propulsion, Structures, and Systems Engineering","lat":"0","long":"0","child_ids":["113"]},{"id":"3","name":"B 22 Ananta ","short_name":"0","group_id":"3","pixel_x":"4695","pixel_y":"925","parent_id":"0","parent_rel":"","description":"Flat nos. 147-206","lat":"0","long":"0","child_ids":[]},{"id":"4","name":"B 23 Aravali ","short_name":"0","group_id":"3","pixel_x":"4404","pixel_y":"968","parent_id":"0","parent_rel":"","description":"Flat nos. 207-267","lat":"0","long":"0","child_ids":[]},{"id":"5","name":"ATM - Canara Bank near Gulmohar","short_name":"Canara ATM","group_id":"6","pixel_x":"2989","pixel_y":"2154","parent_id":"102","parent_rel":"First floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"6","name":"ATM - Canara Bank near H6","short_name":"Canara ATM","group_id":"6","pixel_x":"2500","pixel_y":"748","parent_id":"47","parent_rel":"Near","description":"","lat":"0","long":"0","child_ids":[]},{"id":"7","name":"ATM - State Bank near Tansa","short_name":"SBI ATM","group_id":"6","pixel_x":"3028","pixel_y":"989","parent_id":"95","parent_rel":"Near","description":"","lat":"0","long":"0","child_ids":[]},{"id":"8","name":"Jayantia B-19","short_name":"0","group_id":"3","pixel_x":"1413","pixel_y":"2885","parent_id":"0","parent_rel":"","description":"","lat":"0","long":"0","child_ids":[]},{"id":"9","name":"Badminton Court","short_name":"0","group_id":"8","pixel_x":"3480","pixel_y":"1081","parent_id":"53","parent_rel":"Inside","description":"","lat":"0","long":"0","child_ids":[]},{"id":"10","name":"Bio-diesel Lab","short_name":"0","group_id":"12","pixel_x":"4220","pixel_y":"1558","parent_id":"158","parent_rel":"Backside","description":null,"lat":"0","long":"0","child_ids":[]},{"id":"11","name":"Biosciences and Bioengineering Department","short_name":"BSBE ","group_id":"1","pixel_x":"3934","pixel_y":"2241","parent_id":"0","parent_rel":"","description":"Phone: +912225767771\nFax: +912225767771\nE-mail: office.bio@iitb.ac.in\nThe department offers academic programs in MSc (Biotechnology), MTech (Biomedical Engineering), MSc-PhD Dual Degree Program, PhD Program ","lat":"0","long":"0","child_ids":["211"]},{"id":"12","name":"Boat House","short_name":"0","group_id":"9","pixel_x":"1960","pixel_y":"1757","parent_id":"0","parent_rel":"","description":"Timings: 6 am to 6 pm","lat":"0","long":"0","child_ids":[]},{"id":"13","name":"Brewberrys Cafe","short_name":"Brewberrys","group_id":"5","pixel_x":"2967","pixel_y":"1271","parent_id":"49","parent_rel":"Inside","description":"Ph no: +912265641001, Hostel 8, IIT Bombay, Powai, Mumbai","lat":"0","long":"0","child_ids":[]},{"id":"14","name":"Campus School","short_name":"0","group_id":"7","pixel_x":"3331","pixel_y":"2865","parent_id":"0","parent_rel":"","description":"Principal: MS.BHAGWAT A.S\n+912225768992\nCampus School began as a primary school on 29 June 1976. V to X standard was added by 1986 with 100% results in X std in 1986, 1987 and 1988. The junior college classes FYJC or XI Std and SYJC or XII Std were started in science stream under Principal Chandra Rao in 1989. The Primary to JC complex has about 400 students on its roll, 35 teachers and 20 non-teaching staff. Admission to all classes is restricted to children of IIT employees with some seats made available to the children of NITIE and SAMEER employees.","lat":"0","long":"0","child_ids":[]},{"id":"15","name":"Central Library","short_name":"0","group_id":"1","pixel_x":"3820","pixel_y":"1455","parent_id":"0","parent_rel":"","description":null,"lat":"0","long":"0","child_ids":[]},{"id":"16","name":"Centre for Environmental Science and Engineering","short_name":"CESE","group_id":"1","pixel_x":"4340","pixel_y":"1985","parent_id":"0","parent_rel":"","description":"http:\/\/www.cese.iitb.ac.in\/\nTel +912225767851 Fax +912225764650\nThe Centre offers M.Tech. and Ph.D. programmes, which are interdisciplinary in nature and consists of course work followed by a research project. The duration of the Ph.D. programme varies depending upon the background of the candidate.","lat":"0","long":"0","child_ids":[]},{"id":"17","name":"Chemistry Department","short_name":"Chemistry","group_id":"1","pixel_x":"3788","pixel_y":"2350","parent_id":"27","parent_rel":"","description":"http:\/\/www.chem.iitb.ac.in\/\nPhone: +912225767151 \nFax: +912225723480, +912225767152 \nThe department offers academic programs for M.Sc, Ph.D, (M.Sc + Ph.D) Dual Degree Courses, 4 year BS degree course (From 2014, the 5 year Integrated M.Sc course has been replaced by the 4 year B.S course).","lat":"0","long":"0","child_ids":[]},{"id":"18","name":"Civil Engineering Department","short_name":"Civil","group_id":"1","pixel_x":"3879","pixel_y":"1804","parent_id":"0","parent_rel":"","description":"http:\/\/www.civil.iitb.ac.in\/\nTel:+912225767301\nFax:+912225767302\nThe department offers academic programs for B Tech, Dual Degree (B Tech + M Tech), M Tech, MS and Ph.D across different divisions such as\nBuilding Technology and Construction Management (BTCM)\nEnvironmental and Water Resources Engineering (EWRE)\nGeotechnical Engineering (GT)\nStructural Engineering (ST)\nTransportation Engineering (TR)","lat":"0","long":"0","child_ids":["108","215"]},{"id":"19","name":"Convocation Hall","short_name":"0","group_id":"4","pixel_x":"3255","pixel_y":"1711","parent_id":"0","parent_rel":"","description":"Tel: +912225762781","lat":"0","long":"0","child_ids":[]},{"id":"20","name":"NanoTech. & Science Research Centre","short_name":"CRNTS","group_id":"1","pixel_x":"4081","pixel_y":"1344","parent_id":"0","parent_rel":"","description":"http:\/\/www.iitb.ac.in\/~crnts\/\nTel:+912225767691\nCRNTS offers programs such as\nDual degree programme-1 (B.Tech. Engg. Physics & M.Tech. Engg. Physics with specialization in Nanoscience. Admission Through: JEE. Offered by: Department of Physics. Duration: 5 years)\n\nDual degree programme-2 (M.Sc. Physics & M.Tech. in Materials Science with specialization in Nanoscience., Input : B.Sc. (Physics), Admission through: J.A.M. Jointly offered by Department of Physics & Department of Metallurgical Engg. & Materials Science)\n\nPh.D ( Interdisciplinary program. Research Domains include Nanomaterials, Nanobiotechnology, Nanofluidics, Nanoelectronics, Nanomanufacturing, Nanosensors, Computational research in Nanosystems)","lat":"0","long":"0","child_ids":["1","84"]},{"id":"21","name":"Centre of Studies in Resources Engineering","short_name":"CSRE","group_id":"1","pixel_x":"4096","pixel_y":"1993","parent_id":"0","parent_rel":"","description":"http:\/\/www.csre.iitb.ac.in\/\nTel:+912225767662\nThe centre offers Ph.D, M Tech, UG Minor and institute elective. Research areas include Spatial Analysis, Digital Image Processing, Global Positioning System (GPS) and Photogrammetry, Geocomputational Systems, Microwave Remote Sensing, Snow and Glacier Studies, Geology and Mineral Resources, Agro-Informatics and rural development, Terrain evaluation group, Environment, natural hazards and disaster management, Coastal and marine sciences","lat":"0","long":"0","child_ids":[]},{"id":"22","name":"A1 Director Bungalow","short_name":"Dir. Bunglw.","group_id":"3","pixel_x":"2594","pixel_y":"2495","parent_id":"0","parent_rel":"","description":"","lat":"0","long":"0","child_ids":[]},{"id":"23","name":"Defence Research & Development Organization","short_name":"DRDO","group_id":"3","pixel_x":"4125","pixel_y":"1048","parent_id":"0","parent_rel":"","description":"Flat nos. 101 - 404","lat":"0","long":"0","child_ids":[]},{"id":"24","name":"Earth Science Department","short_name":"Earth Sci","group_id":"1","pixel_x":"4038","pixel_y":"2123","parent_id":"0","parent_rel":"","description":"http:\/\/www.geos.iitb.ac.in\/\n+912225767251,+912225767265\nThe department offers academic programs for M.Sc (Applied Geology, Applied Geophysics, Geoexploration), M Tech (Petroleum Geoscience) and Ph.D. Research areas include Mineralogy, Geochemistry and Ore Deposits Structural Geology Igneous and Metamorphic Petrology Engineering geology, Hydro-geology Sedimentology Stratigraphy and Micro-Paleontology Mathematical Geology\/ Ore Deposit Modelling Rock Magnetism and Marine Geology Seismology, Geothermics","lat":"0","long":"0","child_ids":[]},{"id":"25","name":"Electrical Engineering Annexe Building","short_name":"Elec engg Anx","group_id":"1","pixel_x":"3932","pixel_y":"1997","parent_id":"0","parent_rel":"","description":"http:\/\/www.ee.iitb.ac.in\/\n+912225764408 \n\n","lat":"0","long":"0","child_ids":["110"]},{"id":"26","name":"Electrical Engineering Department","short_name":"Elec engg","group_id":"1","pixel_x":"3780","pixel_y":"1900","parent_id":"0","parent_rel":"","description":"http:\/\/www.ee.iitb.ac.in\/\nMain office is inside GG Building on second floor\nContact persons\nMadhumati Shetty +912225767401\nVaishali Deshpande +912225767402\nSantosh S. Kharat +912225767402\nTanvi D. Shelatkar +912225767402\nB Tech, B Tech Honors, Dual Degree Program (B Tech + M Tech), M Tech (Full time 2 yrs, Part time 3yrs with specializations such as Communications, Engineering (termed as EE1), Control and Computing (EE2), Power Electronics and Power System (EE3), Microelectronics and VLSI (EE4), Electronic Systems (EE5)) and Ph D","lat":"0","long":"0","child_ids":["112"]},{"id":"27","name":"Chemical Engineering Department","short_name":"Chem Engg","group_id":"1","pixel_x":"3788","pixel_y":"2350","parent_id":"0","parent_rel":"","description":"http:\/\/www.che.iitb.ac.in\/\n+912225767201, +912225767202\nPrograms offered in B Tech, M Tech, Dual Degree (M Tech + Ph D) and Ph D. Research areas include Biological Systems Engineering, Energy & Environment, Materials Engineering, Process Systems Engineering, Reactor Engineering, and Transport Phenomena and Complex Fluids","lat":"0","long":"0","child_ids":["17"]},{"id":"28","name":"Electrical Maintenence","short_name":"Elec Maint","group_id":"1","pixel_x":"4544","pixel_y":"1830","parent_id":"0","parent_rel":"","description":"Tel: +912225767971\/ +912225764077","lat":"0","long":"0","child_ids":[]},{"id":"29","name":"Guest House\/ Jalvihar","short_name":"Jalvihar","group_id":"3","pixel_x":"2610","pixel_y":"2138","parent_id":"0","parent_rel":"","description":"Tel: +912225768940 \/ +912225768942 \/ +912225768943","lat":"0","long":"0","child_ids":[]},{"id":"30","name":"Guest House\/ Vanvihar","short_name":"Vanvihar","group_id":"3","pixel_x":"2881","pixel_y":"2106","parent_id":"0","parent_rel":"","description":"Tel: +912225761200 \/ +912225768945","lat":"0","long":"0","child_ids":[]},{"id":"31","name":"Gulmohar Restaurant","short_name":"Gulmohar","group_id":"5","pixel_x":"2989","pixel_y":"2154","parent_id":"102","parent_rel":"Second floor","description":"Tel: +912225762783 \/ Tel: +912225762786","lat":"0","long":"0","child_ids":[]},{"id":"32","name":"Hospital","short_name":"Hosp.","group_id":"9","pixel_x":"3018","pixel_y":"1917","parent_id":"0","parent_rel":"","description":"Hospital Tel: +912225767051,\nAmbulance Tel: +912225761101","lat":"0","long":"0","child_ids":[]},{"id":"33","name":"Hostel 01 Queen of the campus","short_name":"H1","group_id":"2","pixel_x":"3908","pixel_y":"1077","parent_id":"0","parent_rel":"","description":"Hostel security: +912225762601\nHall Manager: +912225762701\nG.Sec: Ratikant +919930836852","lat":"0","long":"0","child_ids":[]},{"id":"34","name":"Hostel 10 Annexe (Girls Hostel)","short_name":"H10 Annx","group_id":"2","pixel_x":"2886","pixel_y":"2452","parent_id":"0","parent_rel":"","description":"Hostel security: +912225762610\nHall Manager: +912225762710\nG.Sec: Madhu Lekha +919769372532","lat":"0","long":"0","child_ids":[]},{"id":"35","name":"Hostel 10 New (Girls Hostel)","short_name":"H10 New","group_id":"2","pixel_x":"3005","pixel_y":"2342","parent_id":"0","parent_rel":"","description":"Hostel security: +912225762610\nHall Manager: +912225762710\nG.Sec: Madhu Lekha +919769372532","lat":"0","long":"0","child_ids":[]},{"id":"36","name":"Hostel 10A QIP building (Girls Hostel)","short_name":"H10A QIP","group_id":"2","pixel_x":"4716","pixel_y":"1448","parent_id":"0","parent_rel":"","description":"Hostel security: +912225762619\nHall Manager: +912225762719\nG.Sec: Sagarika Kumar +919167273231","lat":"0","long":"0","child_ids":[]},{"id":"37","name":"Hostel 11 Athena (Girls Hostel)","short_name":"H11","group_id":"2","pixel_x":"2987","pixel_y":"1368","parent_id":"0","parent_rel":"","description":"Hostel security: +912225762611\nHall Manager: +912225762711\nG.Sec: Nanditha +919769834234","lat":"0","long":"0","child_ids":["161"]},{"id":"38","name":"Hostel 12 Crown of the campus","short_name":"H12","group_id":"2","pixel_x":"2096","pixel_y":"667","parent_id":"0","parent_rel":"","description":"Hostel security: +912225762612\nHall Manager: +912225762712\nG.Sec: Ashutosh +919167782489","lat":"0","long":"0","child_ids":[]},{"id":"39","name":"Hostel 13 House of Titans","short_name":"H13","group_id":"2","pixel_x":"1918","pixel_y":"745","parent_id":"0","parent_rel":"","description":"Hostel security: +912225762613\nHall Manager: +912225762713\nG.Sec: Raj Kumar Yadav +919769484219","lat":"0","long":"0","child_ids":["168"]},{"id":"40","name":"Hostel 14 Silicon ship","short_name":"H14","group_id":"2","pixel_x":"2114","pixel_y":"800","parent_id":"0","parent_rel":"","description":"Hostel security: +912225762614\nHall Manager: 022-25762714\nG.Sec: Mayuresh Pant +919730694513","lat":"0","long":"0","child_ids":[]},{"id":"41","name":"Hostel 15","short_name":"H15","group_id":"2","pixel_x":"4196","pixel_y":"870","parent_id":"0","parent_rel":"","description":"Hostel security: +912225762715\nHall Manager: \nG.Sec:","lat":"0","long":"0","child_ids":[]},{"id":"42","name":"Hostel 16","short_name":"H16","group_id":"2","pixel_x":"3972","pixel_y":"849","parent_id":"0","parent_rel":"","description":"Hostel security: +91222576 2716\nHall Manager: 022-2576\nG.Sec:","lat":"0","long":"0","child_ids":[]},{"id":"43","name":"Hostel 02 The wild ones","short_name":"H2","group_id":"2","pixel_x":"3672","pixel_y":"1000","parent_id":"0","parent_rel":"","description":"Hostel security:+912225762602\nHall Manager: +912225762702\nG.Sec: Manohar Reddy Devarpalli +918796879949","lat":"0","long":"0","child_ids":[]},{"id":"44","name":"Hostel 03 Vitruvians","short_name":"H3 ","group_id":"2","pixel_x":"3435","pixel_y":"946","parent_id":"0","parent_rel":"","description":"Hostel security: +912225762603\nHall Manager: +912225762703\nG.Sec: Arvind Jangid +919820525369","lat":"0","long":"0","child_ids":[]},{"id":"45","name":"Hostel 04 Madhouse","short_name":"H4","group_id":"2","pixel_x":"3176","pixel_y":"867","parent_id":"0","parent_rel":"","description":"Hostel security: +912225762604\nHall Manager: +912225762704\nG.Sec: Kumar Gaurav +919969800320","lat":"0","long":"0","child_ids":[]},{"id":"46","name":"Hostel 05 Penthouse","short_name":"H5","group_id":"2","pixel_x":"2820","pixel_y":"970","parent_id":"0","parent_rel":"","description":"Hostel security: +912225762605\nHall Manager: +912225762705\nG.Sec: Shashank Patidar +919820717487","lat":"0","long":"0","child_ids":[]},{"id":"47","name":"Hostel 06 Vikings","short_name":"H6","group_id":"2","pixel_x":"2500","pixel_y":"748","parent_id":"0","parent_rel":"","description":"Hostel security: +912225762606\nHall Manager:+912225762706\nG.Sec: Anil Reddy +919022623186","lat":"0","long":"0","child_ids":["6"]},{"id":"48","name":"Hostel 07 The lady of the lake","short_name":"H7","group_id":"2","pixel_x":"2454","pixel_y":"942","parent_id":"0","parent_rel":"","description":"Hostel security: +912225762607\nHall Manager: +912225762707\nG.Sec: Archit Laddha +919930239739","lat":"0","long":"0","child_ids":[]},{"id":"49","name":"Hostel 08 Woodland","short_name":"H8","group_id":"2","pixel_x":"2834","pixel_y":"1257","parent_id":"0","parent_rel":"","description":"Hostel security: +912225762608\nHall Manager:+912225762708\nG.Sec: Mayur Kalambe +919920147585","lat":"0","long":"0","child_ids":["13","162"]},{"id":"50","name":"Hostel 09 Nawaabon Ki Basti","short_name":"H9","group_id":"2","pixel_x":"2676","pixel_y":"844","parent_id":"0","parent_rel":"","description":"Hostel security: +912225762609\nHall Manager: +912225762709\nG.Sec: Shubham Meena +919619835583","lat":"0","long":"0","child_ids":[]},{"id":"51","name":"Humanities and Social Sciences Department","short_name":"HSS","group_id":"1","pixel_x":"3911","pixel_y":"2171","parent_id":"0","parent_rel":"","description":"http:\/\/www.hss.iitb.ac.in\/\n+912225767351 \/ +91222576 7351 \/ +912225767352\nThe department offers academic programs for B. Tech, M. Phil, Ph. D. Research areas include Economics, English, Philosophy, Psychology, Sociology","lat":"0","long":"0","child_ids":["212"]},{"id":"52","name":"Industrial Design Centre","short_name":"IDC","group_id":"1","pixel_x":"4207","pixel_y":"1732","parent_id":"0","parent_rel":"","description":"http:\/\/www.idc.iitb.ac.in\n+91222576 7801\nThe department offers academic programs for M. Des and Ph. D. Sub-disciplines include Product Design, Industrial Design, Visual Communication, Animation, Interaction Design, Mobility and vehicle design","lat":"0","long":"0","child_ids":["166","167"]},{"id":"53","name":"Indoor Stadium","short_name":"0","group_id":"8","pixel_x":"3480","pixel_y":"1081","parent_id":"0","parent_rel":"","description":"","lat":"0","long":"0","child_ids":["9"]},{"id":"54","name":"Industrial Research & Consultancy Centre","short_name":"IRCC","group_id":"1","pixel_x":"3505","pixel_y":"1867","parent_id":"88","parent_rel":"Level 2","description":"Tel: +912225767030, +912225767039\nwww.ircc.iitb.ac.in\nThe Industrial Research and Consultancy Centre (IRCC) co-ordinates and facilitates all research and development activities at the Institute.","lat":"0","long":"0","child_ids":[]},{"id":"55","name":"Kanwal Rekhi School of Information Technology ","short_name":"KReSIT","group_id":"1","pixel_x":"3301","pixel_y":"2106","parent_id":"0","parent_rel":"","description":"For admission \/ general queries +9125767967 \/ +9125767977\nOffice +9125767901 \/ +9125767902\nSecurity +912225762784","lat":"0","long":"0","child_ids":["165"]},{"id":"56","name":"Kshitij Udyan","short_name":"0","group_id":"9","pixel_x":"2971","pixel_y":"1744","parent_id":"0","parent_rel":"","description":"","lat":"0","long":"0","child_ids":[]},{"id":"57","name":"Kendriya Vidyalaya ","short_name":"KV","group_id":"7","pixel_x":"3883","pixel_y":"2714","parent_id":"0","parent_rel":"","description":"Tel: +912225768983","lat":"0","long":"0","child_ids":["221"]},{"id":"58","name":"Lake Side Gate no. 1","short_name":"0","group_id":"10","pixel_x":"792","pixel_y":"2777","parent_id":"0","parent_rel":"","description":"Tel: +912225761124","lat":"0","long":"0","child_ids":[]},{"id":"59","name":"Lecture Hall Complex - 1 & 2","short_name":"Lec Hall 1 & 2","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"0","parent_rel":"","description":"","lat":"0","long":"0","child_ids":["173","174","175","176","177","178","179","180","181","182","183","184","185","186","187","188","189","190","191","192","193","194","195","196","197","198","199","200","201","202","203","204","205","206","207","384"]},{"id":"60","name":"Lecture Hall Complex - 3","short_name":"Lec Hall 3","group_id":"4","pixel_x":"3779","pixel_y":"2220","parent_id":"0","parent_rel":"","description":"","lat":"0","long":"0","child_ids":["169","170","171","172"]},{"id":"61","name":"Main Building","short_name":"0","group_id":"1","pixel_x":"3628","pixel_y":"1640","parent_id":"0","parent_rel":"","description":"","lat":"0","long":"0","child_ids":["103","104","105","106","163"]},{"id":"62","name":"Main Gate no. 2","short_name":"0","group_id":"10","pixel_x":"2259","pixel_y":"3237","parent_id":"0","parent_rel":"","description":"Tel: +9125768978 \/ +9125761123. Tum Tum coupons available at Main Gate","lat":"0","long":"0","child_ids":[]},{"id":"63","name":"Market Gate, Y point Gate no. 3","short_name":"Market Gate","group_id":"10","pixel_x":"3829","pixel_y":"2972","parent_id":"0","parent_rel":"","description":"Tel: +912225768979 \/ +912225761121","lat":"0","long":"0","child_ids":[]},{"id":"64","name":"Mathematics Department","short_name":"Maths","group_id":"1","pixel_x":"3928","pixel_y":"1496","parent_id":"0","parent_rel":"","description":"http:\/\/www.math.iitb.ac.in\/\nTel: +912225767451\nB Tech (core courses), MSc (ASI, Maths), Ph D","lat":"0","long":"0","child_ids":["109","111","209","214"]},{"id":"65","name":"Mechanical Engineering Department","short_name":"Mech ","group_id":"1","pixel_x":"4009","pixel_y":"1645","parent_id":"0","parent_rel":"","description":"http:\/\/www.me.iitb.ac.in\/\nTel: +912225762545 Ext. 7500, 7501, 2576 7500, 2576 7501.\nThe department offers academic programs for B. Tech, Dual degree, M. Tech and Ph. D. Research areas include design enggineering, manufacturing enggineering, thermal and fluid enggineering","lat":"0","long":"0","child_ids":["217"]},{"id":"66","name":"Medical Store","short_name":"Med. Store","group_id":"9","pixel_x":"4000","pixel_y":"2808","parent_id":"0","parent_rel":"","description":"","lat":"0","long":"0","child_ids":[]},{"id":"67","name":"Metallurgical Engineering and Material Science Department","short_name":"MEMS","group_id":"1","pixel_x":"3631","pixel_y":"2044","parent_id":"0","parent_rel":"","description":"http:\/\/www.met.iitb.ac.in\/\nTel: +912225767601 \/ +912225767602\nThe department offers academic programs for B. Tech, Dual degree (B Tech + M Tech), M. Tech and Ph. D. Dual degree specializations include Ceramics and Composites and Metallurgical Process Engineering. M Tech specializations include Materials Science, Steel Technology, Process Engineering and Corrosion Science.","lat":"0","long":"0","child_ids":["216","218","219","220"]},{"id":"68","name":"Non- Academic Staff Association","short_name":"NASA","group_id":"1","pixel_x":"4326","pixel_y":"1896","parent_id":"0","parent_rel":"","description":"Tel: +912225768919","lat":"0","long":"0","child_ids":["82"]},{"id":"69","name":"NCC Office","short_name":"0","group_id":"9","pixel_x":"3387","pixel_y":"1421","parent_id":"0","parent_rel":"","description":"Tel: +912225768917","lat":"0","long":"0","child_ids":[]},{"id":"70","name":"Nestle Cafe (Coffee Shack)","short_name":"Coffee Shack","group_id":"5","pixel_x":"3492","pixel_y":"1784","parent_id":"0","parent_rel":"","description":"","lat":"0","long":"0","child_ids":[]},{"id":"71","name":"New Computer Science Engineering Department","short_name":"New CSE","group_id":"1","pixel_x":"3422","pixel_y":"1986","parent_id":"0","parent_rel":"","description":"http:\/\/www.cse.iitb.ac.in\/\nTel: +912225767901\/02\nThe department offers academic programs for B. Tech, Dual degree (B Tech + M Tech), M Tech, Dual Degree PG (M. Tech + Ph. D) and Ph. D. Research areas include algorithms, programming languages and Compilers, database and information systems, artificial intelligence and natural language processing, software engineering, formal methods, distributed systems, computer networks, data mining, computer graphics, computer vision and image understanding, real-time and embedded systems, formal languages and bio-inspired computing","lat":"0","long":"0","child_ids":[]},{"id":"72","name":"B 24 Nilgiri","short_name":"B 24 Nilgiri","group_id":"3","pixel_x":"3318","pixel_y":"2324","parent_id":"0","parent_rel":"","description":"Flat nos. 268-326 ","lat":"0","long":"0","child_ids":[]},{"id":"73","name":"Old Computer Science Engineering Department","short_name":"Old CSE","group_id":"1","pixel_x":"4002","pixel_y":"1545","parent_id":"0","parent_rel":"","description":"http:\/\/www.cse.iitb.ac.in\/\nTel: +912225767701 \/ +912225767702 \/ +912225762771\nThe department offers academic programs for B. Tech, Dual degree (B Tech + M Tech), Dual Degree PG (M. Tech + Ph. D) and Ph. D. Research areas include algorithms, programming languages and Compilers, database and information systems, artificial intelligence and natural language processing, software engineering, formal methods, distributed systems, computer networks, data mining, computer graphics, computer vision and image understanding, real-time and embedded systems, formal languages and bio-inspired computing","lat":"0","long":"0","child_ids":["208"]},{"id":"74","name":"B 19 Old Multistoried Building- Residence ","short_name":"0","group_id":"3","pixel_x":"1413","pixel_y":"2885","parent_id":"0","parent_rel":"","description":"Building lift phone Tel: +912225762884\nFlat nos. 75-98","lat":"0","long":"0","child_ids":[]},{"id":"75","name":"ONGC Research Centre","short_name":"0","group_id":"1","pixel_x":"4234","pixel_y":"2162","parent_id":"0","parent_rel":"","description":"Currently, the centre is working on a project titled \"Physical and Numerical Models for Un-conventional Flood Patterns\". The project relates to increasing country's currrent oil production by means of Enhanced Oil Recovery (EOR) processes. ","lat":"0","long":"0","child_ids":[]},{"id":"76","name":"OrthoCad Lab","short_name":"0","group_id":"12","pixel_x":"4644","pixel_y":"1767","parent_id":"0","parent_rel":"","description":"The OrthoCAD Network Research Cell was established in 2007 to jump-start indigenous research and development activities in orthopaedic reconstruction systems. The OrthoCAD Network addresses a critical need for mega-prostheses to reconstruct massive gaps or loss of bone from osteo-sarcoma (cancer), congenital (birth) defects or trauma (accidents).","lat":"0","long":"0","child_ids":[]},{"id":"77","name":"Padmavati Devi Temple","short_name":"0","group_id":"9","pixel_x":"946","pixel_y":"2178","parent_id":"0","parent_rel":"","description":"","lat":"0","long":"0","child_ids":[]},{"id":"78","name":"PC Saxena Auditorium \/ Leacture Theatre","short_name":"PCSA, LT","group_id":"4","pixel_x":"3648","pixel_y":"1790","parent_id":"0","parent_rel":"","description":"022 2576 4999","lat":"0","long":"0","child_ids":[]},{"id":"79","name":"Physics Department","short_name":"Physics","group_id":"1","pixel_x":"3479","pixel_y":"2247","parent_id":"0","parent_rel":"","description":"The department offers academic programs for B.Tech Engineering Physics (through JEE), Dual degree B.Tech + M.Tech in Engineering Physics with specialisation in Nanoscience (through JEE), MSc Physics 2 Years programme (through JAM), Dual degree programme of MSc and PhD in physics (through JAM). Research areas include Condensed Matter Physics, Photonics and Optics, Nuclear Physics, High Energy Physics, Statistical Physics","lat":"0","long":"0","child_ids":[]},{"id":"80","name":"Post Office","short_name":"0","group_id":"9","pixel_x":"3918","pixel_y":"2846","parent_id":"0","parent_rel":"","description":"Tel: +912225762774","lat":"0","long":"0","child_ids":[]},{"id":"81","name":"Power House","short_name":"0","group_id":"9","pixel_x":"4671","pixel_y":"1590","parent_id":"0","parent_rel":"","description":"","lat":"0","long":"0","child_ids":[]},{"id":"82","name":"Printing Press","short_name":"Press","group_id":"9","pixel_x":"4326","pixel_y":"1896","parent_id":"68","parent_rel":"Inside","description":"Tel: +912225768961","lat":"0","long":"0","child_ids":[]},{"id":"83","name":"Students Activity Centre","short_name":"SAC","group_id":"8","pixel_x":"3599","pixel_y":"1225","parent_id":"0","parent_rel":"","description":"Tel: +912225768968","lat":"0","long":"0","child_ids":["213"]},{"id":"84","name":"Sophisticated Analytical Instruments Facility","short_name":"SAIF","group_id":"1","pixel_x":"4081","pixel_y":"1344","parent_id":"20","parent_rel":"Inside","description":"Tel: +912225767691 \/ +912225767692","lat":"0","long":"0","child_ids":[]},{"id":"85","name":"Seminar Hall","short_name":"0","group_id":"4","pixel_x":"3792","pixel_y":"2025","parent_id":"0","parent_rel":"","description":"Tel: +912225764912, for booking +912225764420","lat":"0","long":"0","child_ids":[]},{"id":"86","name":"Shishu Vihar","short_name":"0","group_id":"9","pixel_x":"2318","pixel_y":"2851","parent_id":"0","parent_rel":"","description":"Shishu Vihar is temporarily located at A5\nTel: +912225764978","lat":"0","long":"0","child_ids":[]},{"id":"87","name":"Shivalik C 23 (187-240)","short_name":"Shivalik C 23","group_id":"3","pixel_x":"3129","pixel_y":"2612","parent_id":"0","parent_rel":"","description":"C- Type Quartera Flat nos. 187 - 240","lat":"0","long":"0","child_ids":[]},{"id":"88","name":"School of Management","short_name":"SOM","group_id":"1","pixel_x":"3505","pixel_y":"1867","parent_id":"0","parent_rel":"","description":"http:\/\/www.som.iitb.ac.in\/\nOffice - +912225767781\nPh. D. admissions - +912225767782\nM. Mgt. admissions - +912225768781 \nThe department offers academic programs in Master Of Management Programme - Full Time, Doctoral Programme in Management - PhD Degree, Management Development Programme - For Corporate Executives","lat":"0","long":"0","child_ids":["54"]},{"id":"89","name":"Staff Canteen","short_name":"Staff Cant.","group_id":"5","pixel_x":"3622","pixel_y":"1547","parent_id":"0","parent_rel":"","description":"Tel: +912225768952","lat":"0","long":"0","child_ids":[]},{"id":"90","name":"Staff Club","short_name":"0","group_id":"8","pixel_x":"2931","pixel_y":"2027","parent_id":"0","parent_rel":"","description":"Tel: +912235764075","lat":"0","long":"0","child_ids":[]},{"id":"91","name":"Staff Hostel","short_name":"0","group_id":"3","pixel_x":"2872","pixel_y":"1472","parent_id":"0","parent_rel":"","description":"Tel: +912225761113","lat":"0","long":"0","child_ids":[]},{"id":"92","name":"State Bank of India, IIT Powai branch","short_name":"SBI","group_id":"6","pixel_x":"2164","pixel_y":"3227","parent_id":"0","parent_rel":"","description":"Phone +912225722894 \/ +912225721103\nwork hours: 10:30 am to 4:30 pm","lat":"0","long":"0","child_ids":[]},{"id":"93","name":"Swimming Pool (new)","short_name":"S. Pool new","group_id":"8","pixel_x":"3558","pixel_y":"1141","parent_id":"0","parent_rel":"","description":"Tel: +912225762755","lat":"0","long":"0","child_ids":[]},{"id":"94","name":"Swimming Pool (old)","short_name":"S. Pool old","group_id":"8","pixel_x":"3742","pixel_y":"1229","parent_id":"0","parent_rel":"","description":"Tel: +912225768967","lat":"0","long":"0","child_ids":[]},{"id":"95","name":"Tansa House King of campus (Proj. Staff Boys)","short_name":"Tansa","group_id":"2","pixel_x":"3028","pixel_y":"932","parent_id":"0","parent_rel":"","description":"Tel: +912225762620","lat":"0","long":"0","child_ids":["7"]},{"id":"96","name":"Tennis Court (new)","short_name":"0","group_id":"8","pixel_x":"3046","pixel_y":"1513","parent_id":"0","parent_rel":"","description":"","lat":"0","long":"0","child_ids":[]},{"id":"97","name":"Tennis Court (old)","short_name":"0","group_id":"8","pixel_x":"3177","pixel_y":"1624","parent_id":"0","parent_rel":"","description":"","lat":"0","long":"0","child_ids":[]},{"id":"98","name":"Victor Menezes Convention Centre","short_name":"VMCC","group_id":"4","pixel_x":"4110","pixel_y":"1847","parent_id":"0","parent_rel":"","description":"Tel: +912225761125","lat":"0","long":"0","child_ids":[]},{"id":"99","name":"Vidya Niwas","short_name":"0","group_id":"3","pixel_x":"4911","pixel_y":"1111","parent_id":"0","parent_rel":"","description":"","lat":"0","long":"0","child_ids":[]},{"id":"100","name":"Vihar House","short_name":"0","group_id":"3","pixel_x":"4558","pixel_y":"1429","parent_id":"0","parent_rel":"","description":"","lat":"0","long":"0","child_ids":[]},{"id":"101","name":"White House","short_name":"0","group_id":"3","pixel_x":"1909","pixel_y":"2799","parent_id":"0","parent_rel":"","description":"B- 20, A wing Tel: +912225762885, Flat nos. 99-110\nB- 20, B wing Tel: +912225762840, Flat nos.111-122","lat":"0","long":"0","child_ids":[]},{"id":"102","name":"Canara Bank","short_name":"0","group_id":"6","pixel_x":"2989","pixel_y":"2154","parent_id":"0","parent_rel":"\n","description":"Tel: +912225762797","lat":"0","long":"0","child_ids":["5","31"]},{"id":"103","name":"Hostel Coordinating Unit","short_name":"HCU","group_id":"1","pixel_x":"3628","pixel_y":"1640","parent_id":"61","parent_rel":"Inside","description":"Chairman Tel: +91222576 8901,\nOfficeTel: +91222576 8900","lat":"0","long":"0","child_ids":[]},{"id":"104","name":"Graduate apptitude test in engineering Office","short_name":"GATE Off.","group_id":"1","pixel_x":"3628","pixel_y":"1640","parent_id":"61","parent_rel":"Inside","description":"Tel: +91222576 2924","lat":"0","long":"0","child_ids":[]},{"id":"105","name":"Joint Admission Test for M.Sc. Office","short_name":"JAM Off.","group_id":"1","pixel_x":"3628","pixel_y":"1640","parent_id":"61","parent_rel":"Inside","description":"Tel: +91222576 2924","lat":"0","long":"0","child_ids":[]},{"id":"106","name":"Joint Entrance Examination Office","short_name":"JEE Off.","group_id":"1","pixel_x":"3628","pixel_y":"1640","parent_id":"61","parent_rel":"Inside","description":"Tel: +91222576 4063","lat":"0","long":"0","child_ids":[]},{"id":"107","name":"Energy Science and enggineering","short_name":"ESE","group_id":"1","pixel_x":"4239","pixel_y":"2028","parent_id":"0","parent_rel":"","description":"http:\/\/www.ese.iitb.ac.in\/\nTel: +912225767890\nThe department offers academic programs in Dual degree (B Tech + M Tech), M Tech, M.Sc.-Ph.D and Ph.D. Research areas include Energy Efficiency and Conservation, Solar PV and Thermal, Battery and Storage Engineering, Hydrogen and Fuel Cells, Smart microgrids, Biomass and Bio-Fuels, Wind Energy, Nuclear","lat":"0","long":"0","child_ids":[]},{"id":"108","name":"Centre for Urban Science and Engineering (inside civil)","short_name":"C-USE","group_id":"1","pixel_x":"3879","pixel_y":"1804","parent_id":"18","parent_rel":"Inside","description":"http:\/\/cuse.iitb.ac.in\/\nTel: +912225769301\nPh. D program. Research areas include Planning and Design (Housing, Land use policies, Public Spaces, Risk Management)\nPolicy and Governance (Housing Economics, Health, Education, Employment, Environment) Infrastructure (Buildings,Transportation & Land use, Urban water, Waste Management, Smart Energy); Informatics (Citizen Science, Cyber-Physical Systems, Urban Knowledge, Geo-Spatial Technologies)","lat":"0","long":"0","child_ids":[]},{"id":"109","name":"Centre for Formal Design and Verification of Software","short_name":"CFDVS","group_id":"1","pixel_x":"3928","pixel_y":"1496","parent_id":"64","parent_rel":"In basement","description":"http:\/\/www.cfdvs.iitb.ac.in\/\n+912225768701","lat":"0","long":"0","child_ids":[]},{"id":"110","name":"Centre for Technology Alternatives for Rural Areas","short_name":"CTARA","group_id":"1","pixel_x":"3932","pixel_y":"1997","parent_id":"25","parent_rel":"Inside","description":"http:\/\/www.ctara.iitb.ac.in\/\nTel: +912225767870\nOffers M. Tech, Ph D and TDSL (Minor for UG). Research areas include agriculture and food, appropriate technology, drinking water, environment, energy and health","lat":"0","long":"0","child_ids":[]},{"id":"111","name":"Centre for Distance Engineering Education Programme","short_name":"CDEEP","group_id":"1","pixel_x":"3928","pixel_y":"1496","parent_id":"64","parent_rel":"Ground floor","description":"http:\/\/www.cdeep.iitb.ac.in\/\nTel: +912225764820\/4812","lat":"0","long":"0","child_ids":[]},{"id":"112","name":"Computer Centre","short_name":"CC","group_id":"1","pixel_x":"3932","pixel_y":"1997","parent_id":"26","parent_rel":"In room 243","description":"http:\/\/www.cc.iitb.ac.in\/\nTel: +912225767751","lat":"0","long":"0","child_ids":[]},{"id":"113","name":"Centre for Aerospace Systems Design and Engineering","short_name":"CASDE","group_id":"1","pixel_x":"4153","pixel_y":"2249","parent_id":"2","parent_rel":"Inside","description":"http:\/\/www.casde.iitb.ac.in\/aboutus\/\nTel: +912225767840","lat":"0","long":"0","child_ids":[]},{"id":"114","name":"Centrifugal Lab","short_name":"0","group_id":"12","pixel_x":"4370","pixel_y":"1395","parent_id":"139","parent_rel":"Near","description":"","lat":"0","long":"0","child_ids":[]},{"id":"115","name":"Concrete Technology Lab","short_name":"Concrete Tech Lab","group_id":"12","pixel_x":"4330","pixel_y":"1495","parent_id":"126","parent_rel":"Near","description":"Comes under Structural Engineering Laboratories of Civil Engineering Department ","lat":"0","long":"0","child_ids":[]},{"id":"116","name":"Cummins Engine Research facility","short_name":"Cummins","group_id":"1","pixel_x":"4350","pixel_y":"1580","parent_id":"0","parent_rel":"","description":"Incharge: Prof. Anuradda Ganesh\nTel: +912225764506\nLocation","lat":"0","long":"0","child_ids":[]},{"id":"117","name":"ENELEK Power Sine","short_name":"ENELEK","group_id":"9","pixel_x":"4160","pixel_y":"1620","parent_id":"158","parent_rel":"Beside","description":"Enelek is a technology driven company, dedicated to delivery to quality and affordability through state-of-the art solar thermal & solar power products, systems and providing technology solutions & services.\nAddress: CM-06, SINE Office\n3rd Floor, CSRE Building\nIIT Bombay\nPowai, Mumbai - 400076\nContact No. - +919167939941 | info@enelek.com\nCareers Enquiry - career@enelek.com","lat":"0","long":"0","child_ids":[]},{"id":"118","name":"Energy Systems Lab","short_name":"Enrgy Sys Lab","group_id":"12","pixel_x":"4230","pixel_y":"1435","parent_id":"121","parent_rel":"Near","description":"Comes under Energy Systems Engineering Department\nhttp:\/\/www.ese.iitb.ac.in\/\n+912225767890\nThe department offers academic programs in Dual degree (B Tech + M Tech), M Tech, M.Sc.-Ph.D and Ph.D. Research areas include Energy Efficiency and Conservation, Solar PV and Thermal, Battery and Storage Engineering, Hydrogen and Fuel Cells, Smart microgrids, Biomass and Bio-Fuels, Wind Energy, Nuclear","lat":"0","long":"0","child_ids":["152"]},{"id":"119","name":"Fluid Mechanics and Fluid Power Lab","short_name":"Fluid Mech Lab","group_id":"12","pixel_x":"4060","pixel_y":"1585","parent_id":"0","parent_rel":"","description":"Comes under Mechanical Engineering Department\nFluid Mechanics Lab Tel: +912225764232 \nFluid Power LabTel: +912225764532 \/ +912225764549","lat":"0","long":"0","child_ids":["128"]},{"id":"120","name":"Fuel Cell Research Facility","short_name":"Fuel Cell Re. Fac.","group_id":"1","pixel_x":"4525","pixel_y":"1680","parent_id":"136","parent_rel":"Inside","description":"Comes under Energy Systems Engineering Department\nhttp:\/\/www.ese.iitb.ac.in\/\n+912225764897","lat":"0","long":"0","child_ids":[]},{"id":"121","name":"Geotechnical Engg. Lab","short_name":"GeoTech Lab","group_id":"12","pixel_x":"4280","pixel_y":"1425","parent_id":"0","parent_rel":"","description":"Comes under Civil Engineering Department\n+912225764320","lat":"0","long":"0","child_ids":["118"]},{"id":"122","name":"GMFL Lab \/ Geophysical and multiphase Flows Lab","short_name":"GMFL Lab","group_id":"12","pixel_x":"4530","pixel_y":"1485","parent_id":"0","parent_rel":"","description":"","lat":"0","long":"0","child_ids":[]},{"id":"123","name":"Greenhouse Lab","short_name":"0","group_id":"12","pixel_x":"4790","pixel_y":"1055","parent_id":"131","parent_rel":"Inside","description":"","lat":"0","long":"0","child_ids":[]},{"id":"124","name":"Heat Pump Lab","short_name":"0","group_id":"12","pixel_x":"4153","pixel_y":"1539","parent_id":"0","parent_rel":"","description":"Comes under Mechanical Engineering Department\n+912225764527 \/ +912225764593","lat":"0","long":"0","child_ids":[]},{"id":"125","name":"Heat Transfer and Thermodynamic Lab","short_name":"Heat Trans Lab","group_id":"12","pixel_x":"4390","pixel_y":"1550","parent_id":"0","parent_rel":"","description":"Comes under Mechanical Engineering Department\n+912225764533","lat":"0","long":"0","child_ids":["153"]},{"id":"126","name":"Heavy Structure Lab","short_name":"0","group_id":"12","pixel_x":"4330","pixel_y":"1495","parent_id":"127","parent_rel":"Near","description":"Comes under Structural Engineering Laboratories of Civil Engineering Department +912225764323","lat":"0","long":"0","child_ids":["115"]},{"id":"127","name":"Hydraulics Lab","short_name":"0","group_id":"12","pixel_x":"4215","pixel_y":"1490","parent_id":"127","parent_rel":"Near","description":"Comes under Civil Engineering Department\nWater Resources Hydraulics Lab +912225764303","lat":"0","long":"0","child_ids":["126","127","129","150"]},{"id":"128","name":"Hydraulics Lab (New)","short_name":"0","group_id":"12","pixel_x":"4110","pixel_y":"1525","parent_id":"119","parent_rel":"Inside","description":"Comes under Civil Engineering Department\nHYDRAULICS LAB (VMCC) +912225764301","lat":"0","long":"0","child_ids":[]},{"id":"129","name":"Hydraulics Lab Workshop","short_name":"0","group_id":"12","pixel_x":"4180","pixel_y":"1450","parent_id":"127","parent_rel":"Near","description":"","lat":"0","long":"0","child_ids":[]},{"id":"130","name":"IC Engine and Combustion Lab","short_name":"Combustion Lab","group_id":"12","pixel_x":"4295","pixel_y":"1570","parent_id":"158","parent_rel":"Backside","description":"Comes under Mechanical Engineering Department\n+912225764586","lat":"0","long":"0","child_ids":["141"]},{"id":"131","name":"K-Yantra Lab (CSE Dept.)","short_name":"K-Yantra","group_id":"1","pixel_x":"4790","pixel_y":"1055","parent_id":"0","parent_rel":"","description":"ERTS Lab\nFirst Floor, KReSIT Building, CSE Department\nIIT Bombay - Powai, Mumbai 400076\nhelpdesk@e-yantra.org","lat":"0","long":"0","child_ids":["123"]},{"id":"132","name":"Machine Lab","short_name":"Mach. Lab","group_id":"12","pixel_x":"1445","pixel_y":"1669","parent_id":"137","parent_rel":"Near","description":"Comes under Electrical Engineering Department\n+912225764422","lat":"0","long":"0","child_ids":[]},{"id":"133","name":"Machine Tool Lab","short_name":"Mach. Tool Lab","group_id":"12","pixel_x":"4410","pixel_y":"1740","parent_id":"148","parent_rel":"Near","description":"Comes under Mechanical Engineering Department\n+912225764518 \/ +912225764537","lat":"0","long":"0","child_ids":[]},{"id":"134","name":"Metal Forming Lab","short_name":"0","group_id":"12","pixel_x":"4290","pixel_y":"1470","parent_id":"150","parent_rel":"Near","description":"Comes under Mechanical Engineering Department\n+912225764561","lat":"0","long":"0","child_ids":[]},{"id":"135","name":"Micro Fluidics Lab","short_name":"0","group_id":"12","pixel_x":"4620","pixel_y":"1783","parent_id":"0","parent_rel":"","description":"","lat":"0","long":"0","child_ids":["144"]},{"id":"136","name":"N1 Bay","short_name":"0","group_id":"1","pixel_x":"4525","pixel_y":"1680","parent_id":"154","parent_rel":"Near","description":"Comes under Chemical Engineering Department\n+912225764211","lat":"0","long":"0","child_ids":["120"]},{"id":"137","name":"N2 Bay","short_name":"0","group_id":"1","pixel_x":"4445","pixel_y":"1669","parent_id":"154","parent_rel":"Near","description":"","lat":"0","long":"0","child_ids":["132"]},{"id":"138","name":"N3 Bay","short_name":"0","group_id":"1","pixel_x":"4360","pixel_y":"1645","parent_id":"154","parent_rel":"Near","description":"","lat":"0","long":"0","child_ids":[]},{"id":"139","name":"National Geotechnical Centrifuge Facility","short_name":"GeoTech Centrifuge","group_id":"1","pixel_x":"4370","pixel_y":"1395","parent_id":"0","parent_rel":"","description":"","lat":"0","long":"0","child_ids":["114"]},{"id":"140","name":"OrthoCad Lab","short_name":"0","group_id":"12","pixel_x":"4683","pixel_y":"1702","parent_id":"0","parent_rel":"","description":"Comes under Mechanical Engineering Department\n+912225764399","lat":"0","long":"0","child_ids":[]},{"id":"141","name":"Old ONGC Lab","short_name":"0","group_id":"12","pixel_x":"4275","pixel_y":"1555","parent_id":"130","parent_rel":"Near","description":"","lat":"0","long":"0","child_ids":[]},{"id":"142","name":"Physics Lab (Ist Years)","short_name":"Phy Lab (1 Yr)","group_id":"12","pixel_x":"4585","pixel_y":"1540","parent_id":"0","parent_rel":"","description":"Comes under Physics department","lat":"0","long":"0","child_ids":["160"]},{"id":"143","name":"Refrigeration, A\/C and Cryogenics Lab","short_name":"0","group_id":"12","pixel_x":"4225","pixel_y":"1630","parent_id":"158","parent_rel":"Near","description":"Comes under Mechanical Engineering Department\n+912225764587","lat":"0","long":"0","child_ids":[]},{"id":"144","name":"RM Lab (Rapid manufacturing)","short_name":"RM Lab","group_id":"12","pixel_x":"4650","pixel_y":"1757","parent_id":"135","parent_rel":"Near","description":"","lat":"0","long":"0","child_ids":[]},{"id":"145","name":"Rock Cutting Lab","short_name":"0","group_id":"12","pixel_x":"3921","pixel_y":"2095","parent_id":"146","parent_rel":"Near","description":"","lat":"0","long":"0","child_ids":[]},{"id":"146","name":"Rock Powdering Lab","short_name":"0","group_id":"12","pixel_x":"3921","pixel_y":"2095","parent_id":"0","parent_rel":"","description":"","lat":"0","long":"0","child_ids":["145"]},{"id":"147","name":"S1 Bay","short_name":"0","group_id":"1","pixel_x":"4490","pixel_y":"1760","parent_id":"151","parent_rel":"Near","description":"","lat":"0","long":"0","child_ids":["155"]},{"id":"148","name":"S2 Bay","short_name":"0","group_id":"1","pixel_x":"4410","pixel_y":"1740","parent_id":"151","parent_rel":"Near","description":"Tel:+912225764213","lat":"0","long":"0","child_ids":["133","159"]},{"id":"149","name":"S3 Bay","short_name":"0","group_id":"1","pixel_x":"4325","pixel_y":"1720","parent_id":"151","parent_rel":"Near","description":"","lat":"0","long":"0","child_ids":[]},{"id":"150","name":"Structural Evaluation & Material Technologies Lab","short_name":"SEMT Lab","group_id":"12","pixel_x":"4280","pixel_y":"1510","parent_id":"127","parent_rel":"Near","description":"Comes under Civil Engineering Department\n+912225764318","lat":"0","long":"0","child_ids":["134"]},{"id":"151","name":"Structural integrity Testing and Analysis Centre","short_name":"SITAC","group_id":"1","pixel_x":"4355","pixel_y":"1750","parent_id":"0","parent_rel":"","description":"Comes under Mechanical Engineering Department\n+912225764528","lat":"0","long":"0","child_ids":["147","148","149"]},{"id":"152","name":"Solar Lab","short_name":"0","group_id":"12","pixel_x":"4230","pixel_y":"1435","parent_id":"118","parent_rel":"","description":"Comes under Chemistry Department\n+912225764887\nSOLAR LAB (308) Phone: +912225764173 ","lat":"0","long":"0","child_ids":[]},{"id":"153","name":"Steam Power Lab","short_name":"0","group_id":"12","pixel_x":"4376","pixel_y":"1526","parent_id":"125","parent_rel":"","description":"Comes under Mechanical Engineering Department\n+912225764584","lat":"0","long":"0","child_ids":[]},{"id":"154","name":"SMAmL Suman Mashruwala Advanced Microengineering Lab","short_name":"Adv. MicroEngg Lab","group_id":"12","pixel_x":"4431","pixel_y":"1615","parent_id":"0","parent_rel":"","description":"Phone: +912225767519 \/ +912225764534\nFax:-+912225726875\nE-mail: gandhi@me.iitb.ac.in","lat":"0","long":"0","child_ids":["136","137","138"]},{"id":"155","name":"Supercritical fluid Processing facility (Chemical Engg.)","short_name":"Fluid Processing","group_id":"1","pixel_x":"4490","pixel_y":"1760","parent_id":"147","parent_rel":"","description":"Comes under Chemical Engineering Department\n+912225767201 \/ +912225767202","lat":"0","long":"0","child_ids":[]},{"id":"156","name":"Thermal Hydraulic Test Facility","short_name":"Hydraulic Test","group_id":"1","pixel_x":"4463","pixel_y":"1536","parent_id":"0","parent_rel":"","description":"Comes under Mechanical Engineering Department\n+912225762545 Ext. 7500, 7501, 2576 7500, 2576 7501.","lat":"0","long":"0","child_ids":[]},{"id":"157","name":"Tinkerers Lab (STAB)","short_name":"0","group_id":"12","pixel_x":"4225","pixel_y":"1630","parent_id":"158","parent_rel":"","description":"","lat":"0","long":"0","child_ids":[]},{"id":"158","name":"Treelabs","short_name":"0","group_id":"9","pixel_x":"4225","pixel_y":"1630","parent_id":"0","parent_rel":"","description":"TreeLabs is an 'inventions factory' to nurture and encourage inventors and innovations, leading to entrepreneurship\nAddress: Electrical Engineering Dept, \nN-5 Bay (near Mech Engg Dept), \nI.I.T.Bombay, Powai, \nMumbai - 400076, India. \nPhone: +912225723001 \/ +912225764410\nEmail: Prof. Dipankar : dipankar@iitbombay.org","lat":"0","long":"0","child_ids":["10","117","130","143","157"]},{"id":"159","name":"UG Lab \/ S2 Bay","short_name":"0","group_id":"12","pixel_x":"4410","pixel_y":"1740","parent_id":"148","parent_rel":"","description":"Comes under Chemical Engineering Department \n+912225764207","lat":"0","long":"0","child_ids":[]},{"id":"160","name":"UG Lab (Ist Years)","short_name":"0","group_id":"12","pixel_x":"4585","pixel_y":"1540","parent_id":"142","parent_rel":"","description":"","lat":"0","long":"0","child_ids":[]},{"id":"161","name":"Printing and photocopying H11","short_name":"Prints","group_id":"11","pixel_x":"2987","pixel_y":"1368","parent_id":"37","parent_rel":"Inside","description":"","lat":"0","long":"0","child_ids":[]},{"id":"162","name":"Printing and photocopying H8","short_name":"Prints","group_id":"11","pixel_x":"2834","pixel_y":"1257","parent_id":"49","parent_rel":"Inside","description":"","lat":"0","long":"0","child_ids":[]},{"id":"163","name":"Printing and photocopying Main Building","short_name":"Prints","group_id":"11","pixel_x":"3628","pixel_y":"1640","parent_id":"61","parent_rel":"Inside","description":"","lat":"0","long":"0","child_ids":[]},{"id":"164","name":"ATM - State Bank main gate","short_name":"SBI ATM","group_id":"6","pixel_x":"2164","pixel_y":"3227","parent_id":"0","parent_rel":"","description":"","lat":"0","long":"0","child_ids":[]},{"id":"165","name":"KReSIT Canteen","short_name":"KReSIT Canteen","group_id":"5","pixel_x":"3301","pixel_y":"2106","parent_id":"55","parent_rel":"Inside","description":"From 10 to 8. Samosas run out by 5:30ish though!","lat":"0","long":"0","child_ids":[]},{"id":"166","name":"IDC Canteen","short_name":"IDC Cant.","group_id":"5","pixel_x":"4207","pixel_y":"1732","parent_id":"52","parent_rel":"Inside","description":"Santosh bhaiya's Canteen +918652423193\n9am to 5:30 pm, weekdays only\nMenu: Tea, Coffee, Upma, Poha, Idli Chutney, Meduwada, Samosa, manchurian roll, paneer roll, chicken roll, Vada Paav, biscuits, Maggi, Tropicana, cold drinks","lat":"0","long":"0","child_ids":[]},{"id":"167","name":"IDC Shakti","short_name":"Shakti","group_id":"5","pixel_x":"4207","pixel_y":"1732","parent_id":"52","parent_rel":"Inside","description":"Piping hot, home style food between 1 pm and 2:30 pm, weekdays only!\nCall Mr. Gaikwad to order a tiffin at +919833575881","lat":"0","long":"0","child_ids":[]},{"id":"168","name":"H13 Night Canteen","short_name":"H13 Night Cant.","group_id":"5","pixel_x":"1918","pixel_y":"745","parent_id":"39","parent_rel":"Inside","description":"Open till 3 am, recomended for night-outs!","lat":"0","long":"0","child_ids":[]},{"id":"169","name":"HALL 1 (LA 101)","short_name":"0","group_id":"4","pixel_x":"3779","pixel_y":"2220","parent_id":"60","parent_rel":"Ground and First floors","description":"The classroom has 4 entrance doors, two on ground floor and two in first floor.","lat":"0","long":"0","child_ids":[]},{"id":"170","name":"HALL 2 (LA 102)","short_name":"0","group_id":"4","pixel_x":"3779","pixel_y":"2220","parent_id":"60","parent_rel":"Ground and First floors","description":"The classroom has 4 entrance doors, two on ground floor and two in first floor.","lat":"0","long":"0","child_ids":[]},{"id":"171","name":"HALL 3 (LA 103)","short_name":"0","group_id":"4","pixel_x":"3779","pixel_y":"2220","parent_id":"60","parent_rel":"Second and Third floors","description":"The classroom has 4 entrance doors, two on second floor and two in third floor.","lat":"0","long":"0","child_ids":[]},{"id":"172","name":"HALL 4 (LA 104)","short_name":"0","group_id":"4","pixel_x":"3779","pixel_y":"2220","parent_id":"60","parent_rel":"Second and Third floors","description":"The classroom has 4 entrance doors, two on second floor and two in third floor.","lat":"0","long":"0","child_ids":[]},{"id":"173","name":"LT 001 (LCT 01)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"Ground floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"174","name":"LT 002 (LCT 02)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"Ground floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"175","name":"LT 004 (LCT 04)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"Ground floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"176","name":"LT 005 (LCT 05)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"Ground floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"177","name":"LT 006 (LCT 06)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"Ground floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"178","name":"LT 101 (LCT 11)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"First floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"179","name":"LT 102 (LCT 12)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"First floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"180","name":"LT 103 (LCT 13)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"First floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"181","name":"LT 104 (LCT 14)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"First floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"182","name":"LT 105 (LCT 15)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"First floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"183","name":"LT 106 (LCT 16)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"First floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"184","name":"LT 201 (LCT 21)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"Second floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"185","name":"LT 202 (LCT 22)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"Second floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"186","name":"LT 203 (LCT 23)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"Second floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"187","name":"LT 204 (LCT 24)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"Second floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"188","name":"LT 205 (LCT 25)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"Second floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"189","name":"LT 206 (LCT 26)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"Second floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"190","name":"LT 301 (LCT 31)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"Third floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"191","name":"LT 302 (LCT 32)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"Third floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"192","name":"LT 303 (LCT 33)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"Third floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"193","name":"LT 304 (LCT 34)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"Third floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"194","name":"LT 305 (LCT 35)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"Third floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"195","name":"LT 306 (LCT 36)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"Third floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"196","name":"LC 001 (LCC 1)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"Ground floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"197","name":"LC 002 (LCC 2)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"Ground floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"198","name":"LC 101 (LCC 11)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"First floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"199","name":"LC 102 (LCC 12)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"First floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"200","name":"LC 201 (LCC 21)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"Second floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"201","name":"LC 202 (LCC 22)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"Second floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"202","name":"LC 301 (LCC 31)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"Third floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"203","name":"LC 302 (LCC 32)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"Third floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"204","name":"LH 101 (LCH 11)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"First floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"205","name":"LH 102 (LCH 12)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"First floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"206","name":"LH 301 (LCH 31)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"Third floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"207","name":"LH 302 (LCH 32)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"Third floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"208","name":"New Software Lab","short_name":"NSL","group_id":"12","pixel_x":"4002","pixel_y":"1545","parent_id":"73","parent_rel":"Ground floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"209","name":"Old Software Lab","short_name":"OSL","group_id":"12","pixel_x":"3928","pixel_y":"1496","parent_id":"64","parent_rel":"Ground floor","description":"","lat":"0","long":"0","child_ids":[]},{"id":"210","name":"Inter-disciplinary Programme in Systems and Control Engineering","short_name":"IDP Sys & Cntrl Engg.","group_id":"1","pixel_x":"4011","pixel_y":"1411","parent_id":"0","parent_rel":"","description":"http:\/\/www.sc.iitb.ac.in\/\nTel: +912225767884, +912225722545\nFax:+912225720057\nM Tech and Ph D offered in this programme. Research ares include nonlinear control, robotics, path-planning, embedded control, coordination of autonomous vehicles, multi-agent systems, game theory, information theory, combinatorics, sliding mode control and applications, fractional-order modelling and control, optimization and optimization-based control, and stochastic processes. In addition, research in the areas of process control, identification, behavioural theory, matrix computation, automotive control are being pursued by the associate faculty members. ","lat":"0","long":"0","child_ids":[]},{"id":"211","name":"WRCBB Wadhwani Research Centre in Biosciences and Bioengineering ","short_name":"Wadhwani Research Centre BB","group_id":"1","pixel_x":"3934","pixel_y":"2241","parent_id":"11","parent_rel":"Inside","description":"","lat":"0","long":"0","child_ids":[]},{"id":"212","name":"Aerospace Engineering Annexe","short_name":"Aero Annx","group_id":"1","pixel_x":"3911","pixel_y":"2171","parent_id":"51","parent_rel":"Inside","description":"http:\/\/www.aero.iitb.ac.in\/\nPhone No.: +912225764111\nFax No.: +912225722602.\nEmail: office@aero.iitb.ac.in \nThe department offers academic programs for B. Tech, M. Tech, Ph. D. Specialization are offered: Aerodynamics, Control and Guidance, Propulsion, Structures, and Systems Engineering","lat":"0","long":"0","child_ids":[]},{"id":"213","name":"Open Air Theatre","short_name":"OAT","group_id":"8","pixel_x":"3599","pixel_y":"1225","parent_id":"83","parent_rel":"Inside","description":"Tel: +912225768968","lat":"0","long":"0","child_ids":[]},{"id":"214","name":"Inter-disciplinary Programme in Educational Technology","short_name":"IDP Edu Tech","group_id":"1","pixel_x":"3928","pixel_y":"1496","parent_id":"64","parent_rel":"Inside","description":"http:\/\/www.et.iitb.ac.in\/\nMain Office: Mathematics Building, Near Central Library.\nTel:+912225764820\nFax: +912225764812\nPh.D. is offered in this programme. Research areas include Pan-Domain Cognitive Abilities, Teacher Use of Educational Technology Tools and Strategies, Educational Technology Tools.","lat":"0","long":"0","child_ids":[]},{"id":"215","name":"Inter-disciplinary Programme in Climate Studies","short_name":"IDP Climate Studies","group_id":"1","pixel_x":"3879","pixel_y":"1804","parent_id":"18","parent_rel":"Inside","description":"http:\/\/www.climate.iitb.ac.in\/\nOffice inside Civil Engineering building\nTel:+912225767301\nFax:+912225767302\nPh.D. is offered in this programme. Research areas include Climate science and technology, Technology evaluation and assessment, Impacts, Vulnerability and Adaptation","lat":"0","long":"0","child_ids":[]},{"id":"216","name":"Inter-disciplinary Programme in Corrosion Science & Engineering","short_name":"IDP Corro Sci & Engg","group_id":"1","pixel_x":"3631","pixel_y":"2044","parent_id":"67","parent_rel":"Inside","description":"http:\/\/www.iitb.ac.in\/~corrsci\/\nOffice inside Metallurgical Engineering and Material Science building\nTel: +912225767601 \/ +912225767602\nPh. D and M.Tech offered in this programme. Research focuses on corrosion and its control with applications in industris such as Oil and gas industry, Marine and aerospace industry, Automobile industry, Building and constructions, General engineering industry, Power plants, etc.","lat":"0","long":"0","child_ids":[]},{"id":"217","name":"Industrial Engineering and Operations Research","short_name":"IDP IEOR","group_id":"1","pixel_x":"4009","pixel_y":"1645","parent_id":"65","parent_rel":"Inside","description":"http:\/\/www.ieor.iitb.ac.in\/\nRoom 308A, Mechanical Engineering Building,\nIndian Institute of Technology Bombay,\nPowai, Mumbai (INDIA), PIN: 400076, \nFax: +912225726875, +912225723480\nM.Tech, Dual Degree (MSc-PhD) and PhD offered in this programme. Research areas include Optimization: Models, theory and algorithms, Stochastic models, Stochastic control, Simulation Modeling and Analysis, Artificial Intelligence based methods, Game theory, Logistics and Transportation, Supply Chain, Analysis and Inventory Planning, Financial Engineering, Optimization, Planning and Control in Manufacturing and Robotics, Scheduling and ERP","lat":"0","long":"0","child_ids":[]},{"id":"218","name":"Aqueous corrosion lab","short_name":"Aq Corro Lab","group_id":"12","pixel_x":"3631","pixel_y":"2044","parent_id":"67","parent_rel":"Inside","description":"Tel: +912225764607","lat":"0","long":"0","child_ids":[]},{"id":"219","name":"Corrosion lab I","short_name":"Corro Lab I","group_id":"12","pixel_x":"3631","pixel_y":"2044","parent_id":"67","parent_rel":"Inside","description":"Tel: +912225764618","lat":"0","long":"0","child_ids":[]},{"id":"220","name":"Corrosion science paint lab","short_name":"Corro Sci Paint Lab","group_id":"12","pixel_x":"3631","pixel_y":"2044","parent_id":"67","parent_rel":"Inside","description":"Tel: +912225764606","lat":"0","long":"0","child_ids":[]},{"id":"221","name":"K.G School","short_name":"0","group_id":"7","pixel_x":"3883","pixel_y":"2714","parent_id":"57","parent_rel":"Inside","description":"Principal: Ms. Lata P. Jagdeesh\nhttp:\/\/www.iitb.ac.in\/facilities\/kgschool\/\nSchool Office: +912225768991\nIn Charge's Office: +912225768913\nEmail: kgschool@iitb.ac.in\nIn 1963 for the benefit of the children of the staff members staying in the campus of IIT Bombay, a School consisting of K.G. and primary classes commenced functioning from 10th June 1963. This School had one Nursery class, one Kindergarten class and one class each of I and II (4 classes). From a small number of 53 students at the start today the School has 250 children on roll, 7 teaching staff, 12 supporting staff and one office staff working with the School In Charge.\n","lat":"0","long":"0","child_ids":[]},{"id":"222","name":"Society for Applied Microwave Electronics Engineering & Research","short_name":"SAMEER ","group_id":"1","pixel_x":"4538","pixel_y":"837","parent_id":"0","parent_rel":"","description":"http:\/\/www.sameer.gov.in\/\nPhone: +912225727100\nFax: +912225723254\nSAMEER was set up as an autonomous R & D laboratory at Mumbai under the then Department of Electronics, Government of India with a broad mandate to undertake R & D work in the areas of Microwave Engineering and Electromagnetic Engineering Technology. It is an offshoot of the special microwave products unit (SMPU) set up in 1977 at the TATA INSTITUTE OF FUNDAMENTAL RESEARCH (TIFR), Mumbai. SAMEER, Mumbai was setup in 1984.","lat":"0","long":"0","child_ids":[]},{"id":"223","name":"Sameer Hill","short_name":"0","group_id":"9","pixel_x":"4830","pixel_y":"675","parent_id":"0","parent_rel":"","description":"","lat":"0","long":"0","child_ids":[]},{"id":"224","name":"C22, A wing, Sahyadri","short_name":"Sahyadri","group_id":"3","pixel_x":"4657","pixel_y":"1093","parent_id":"0","parent_rel":"","description":"Hill side, Flat nos. 151 - 168","lat":"0","long":"0","child_ids":[]},{"id":"225","name":"B21 Satpura ","short_name":"","group_id":"3","pixel_x":"3332","pixel_y":"2602","parent_id":"0","parent_rel":"","description":"","lat":"0","long":"0","child_ids":[]},{"id":"226","name":"Girish Gaitonde Building","short_name":"GG Bldg","group_id":"1","pixel_x":"3668","pixel_y":"1937","parent_id":"0","parent_rel":"","description":"Contact persons:\nMadhumati Shetty +912225767401\nVaishali Deshpande +912225767402\nSantosh S. Kharat +912225767402\nTanvi D. Shelatkar +912225767402","lat":"0","long":"0","child_ids":[]},{"id":"227","name":"Uphar","short_name":"0","group_id":"5","pixel_x":"4052","pixel_y":"2815","parent_id":"0","parent_rel":"","description":"Upkar food joint\nBreakfast: 6:30 am to 12 pm\nLunch: 12pm to 3 pm\nEvening snacks: 4 pm to 7:30 pm","lat":"0","long":"0","child_ids":[]},{"id":"228","name":"Campus Hub","short_name":"0","group_id":"5","pixel_x":"2815","pixel_y":"1067","parent_id":"0","parent_rel":"","description":null,"lat":"0","long":"0","child_ids":[]},{"id":"229","name":"C22, B wing, Vindya","short_name":"Vindya","group_id":"3","pixel_x":"4651","pixel_y":"1093","parent_id":"0","parent_rel":"","description":"Hill side, Flat nos. 169 - 186","lat":"0","long":"0","child_ids":[]},{"id":"230","name":"Tulsi A","short_name":"0","group_id":"3","pixel_x":"4515","pixel_y":"952","parent_id":"0","parent_rel":"","description":"PS Quarters","lat":"0","long":"0","child_ids":[]},{"id":"231","name":"Tulsi B","short_name":"0","group_id":"3","pixel_x":"4573","pixel_y":"987","parent_id":"0","parent_rel":"","description":"PS Quarters","lat":"0","long":"0","child_ids":[]},{"id":"232","name":"Tulsi C","short_name":"0","group_id":"3","pixel_x":"4607","pixel_y":"1031","parent_id":"0","parent_rel":"","description":"PS Quarters","lat":"0","long":"0","child_ids":[]},{"id":"233","name":"2B 1 ","short_name":"0","group_id":"3","pixel_x":"4421","pixel_y":"2264","parent_id":"0","parent_rel":"","description":"2B-Type Quarters, Flat nos 1 - 6","lat":"0","long":"0","child_ids":[]},{"id":"234","name":"2B 2","short_name":"0","group_id":"3","pixel_x":"4381","pixel_y":"2311","parent_id":"0","parent_rel":"","description":"2B-Type Quarters, Flat nos 7 - 12","lat":"0","long":"0","child_ids":[]},{"id":"235","name":"2B 3","short_name":"0","group_id":"3","pixel_x":"4331","pixel_y":"2388","parent_id":"0","parent_rel":"","description":"2B-Type Quarters, Flat nos 13 - 18","lat":"0","long":"0","child_ids":[]},{"id":"236","name":"2B 4","short_name":"0","group_id":"3","pixel_x":"4284","pixel_y":"2462","parent_id":"0","parent_rel":"","description":"2B-Type Quarters, Flat nos 19 - 24","lat":"0","long":"0","child_ids":[]},{"id":"237","name":"2B 5","short_name":"0","group_id":"3","pixel_x":"4196","pixel_y":"2455","parent_id":"0","parent_rel":"","description":"2B-Type Quarters, Flat nos 25 - 30","lat":"0","long":"0","child_ids":[]},{"id":"238","name":"2B 6","short_name":"0","group_id":"3","pixel_x":"4243","pixel_y":"2391","parent_id":"0","parent_rel":"","description":"2B-Type Quarters, Flat nos 31 - 36","lat":"0","long":"0","child_ids":[]},{"id":"239","name":"2B 7","short_name":"0","group_id":"3","pixel_x":"4296","pixel_y":"2312","parent_id":"0","parent_rel":"","description":"2B-Type Quarters, Flat nos 37 - 42","lat":"0","long":"0","child_ids":[]},{"id":"240","name":"2B 8","short_name":"0","group_id":"3","pixel_x":"4348","pixel_y":"2247","parent_id":"0","parent_rel":"","description":"2B-Type Quarters, Flat nos 43 - 48","lat":"0","long":"0","child_ids":[]},{"id":"241","name":"2B 9","short_name":"0","group_id":"3","pixel_x":"4384","pixel_y":"2192","parent_id":"0","parent_rel":"","description":"2B-Type Quarters, Flat nos 49 - 54","lat":"0","long":"0","child_ids":[]},{"id":"242","name":"2B 11","short_name":"0","group_id":"3","pixel_x":"808","pixel_y":"2612","parent_id":"0","parent_rel":"","description":"2B-Type Quarters, Flat nos 61 - 66","lat":"0","long":"0","child_ids":[]},{"id":"243","name":"2B 12","short_name":"0","group_id":"3","pixel_x":"722","pixel_y":"2624","parent_id":"0","parent_rel":"","description":"2B-Type Quarters, Flat nos 67 - 72","lat":"0","long":"0","child_ids":[]},{"id":"244","name":"2B 13","short_name":"0","group_id":"3","pixel_x":"691","pixel_y":"2555","parent_id":"0","parent_rel":"","description":"2B-Type Quarters, Flat nos 73 - 78","lat":"0","long":"0","child_ids":[]},{"id":"245","name":"2B 14","short_name":"0","group_id":"3","pixel_x":"1144","pixel_y":"2866","parent_id":"0","parent_rel":"","description":"2B-Type Quarters, Flat nos 79 - 84","lat":"0","long":"0","child_ids":[]},{"id":"246","name":"2B 15","short_name":"0","group_id":"3","pixel_x":"1076","pixel_y":"2833","parent_id":"0","parent_rel":"","description":"2B-Type Quarters, Flat nos 85 - 90","lat":"0","long":"0","child_ids":[]},{"id":"247","name":"2B 16","short_name":"0","group_id":"3","pixel_x":"908","pixel_y":"2798","parent_id":"0","parent_rel":"","description":"2B-Type Quarters, Flat nos 91 - 96","lat":"0","long":"0","child_ids":[]},{"id":"248","name":"2B 17","short_name":"0","group_id":"3","pixel_x":"878","pixel_y":"2756","parent_id":"0","parent_rel":"","description":"2B-Type Quarters, Flat nos 97 - 102","lat":"0","long":"0","child_ids":[]},{"id":"249","name":"2B 18","short_name":"0","group_id":"3","pixel_x":"615","pixel_y":"2492","parent_id":"0","parent_rel":"","description":"2B-Type Quarters, Flat nos 103 - 108","lat":"0","long":"0","child_ids":[]},{"id":"250","name":"2B 19","short_name":"0","group_id":"3","pixel_x":"2573","pixel_y":"2468","parent_id":"0","parent_rel":"","description":"2B-Type Quarters, Flat nos 109 - 114","lat":"0","long":"0","child_ids":[]},{"id":"251","name":"2B 20","short_name":"0","group_id":"3","pixel_x":"4786","pixel_y":"1431","parent_id":"0","parent_rel":"","description":"2B-Type Quarters, Flat nos 115 - 134","lat":"0","long":"0","child_ids":[]},{"id":"252","name":"2B 21","short_name":"0","group_id":"3","pixel_x":"4723","pixel_y":"1371","parent_id":"0","parent_rel":"","description":"2B-Type Quarters, Flat nos 135 - 140","lat":"0","long":"0","child_ids":[]},{"id":"253","name":"2B 22","short_name":"0","group_id":"3","pixel_x":"4748","pixel_y":"1370","parent_id":"0","parent_rel":"","description":"2B-Type Quarters, Flat nos 141 - 164","lat":"0","long":"0","child_ids":[]},{"id":"254","name":"2B 23","short_name":"0","group_id":"3","pixel_x":"4365","pixel_y":"1180","parent_id":"0","parent_rel":"","description":"2B-Type Quarters, Flat nos 165 - 192","lat":"0","long":"0","child_ids":[]},{"id":"255","name":"2B 24","short_name":"0","group_id":"3","pixel_x":"4124","pixel_y":"1238","parent_id":"0","parent_rel":"","description":"2B-Type Quarters, Flat nos 193 - 220","lat":"0","long":"0","child_ids":[]},{"id":"256","name":"A2 Bungalow","short_name":"A2","group_id":"3","pixel_x":"2491","pixel_y":"2581","parent_id":"0","parent_rel":"","description":"A-Type Bungalow","lat":"0","long":"0","child_ids":[]},{"id":"257","name":"A3 Bungalow","short_name":"A3","group_id":"3","pixel_x":"2415","pixel_y":"2682","parent_id":"0","parent_rel":"","description":"A-Type Bungalow","lat":"0","long":"0","child_ids":[]},{"id":"258","name":"A4 Bungalow","short_name":"A4","group_id":"3","pixel_x":"2373","pixel_y":"2767","parent_id":"0","parent_rel":"","description":"A-Type Bungalow","lat":"0","long":"0","child_ids":[]},{"id":"259","name":"A5 Bungalow","short_name":"A5","group_id":"3","pixel_x":"2319","pixel_y":"2848","parent_id":"0","parent_rel":"","description":"A-Type Bungalow","lat":"0","long":"0","child_ids":[]},{"id":"260","name":"A6 Bungalow","short_name":"A6","group_id":"3","pixel_x":"2254","pixel_y":"2963","parent_id":"0","parent_rel":"","description":"A-Type Bungalow","lat":"0","long":"0","child_ids":[]},{"id":"261","name":"A7 Bungalow","short_name":"A7","group_id":"3","pixel_x":"2211","pixel_y":"3055","parent_id":"0","parent_rel":"","description":"A-Type Bungalow","lat":"0","long":"0","child_ids":[]},{"id":"262","name":"A8 Bungalow","short_name":"A8","group_id":"3","pixel_x":"2176","pixel_y":"3135","parent_id":"0","parent_rel":"","description":"A-Type Bungalow","lat":"0","long":"0","child_ids":[]},{"id":"263","name":"A9 Bungalow","short_name":"A9","group_id":"3","pixel_x":"1888","pixel_y":"2960","parent_id":"0","parent_rel":"","description":"A-Type Bungalow","lat":"0","long":"0","child_ids":[]},{"id":"264","name":"A10 Bungalow","short_name":"A10","group_id":"3","pixel_x":"1962","pixel_y":"2928","parent_id":"0","parent_rel":"","description":"A-Type Bungalow","lat":"0","long":"0","child_ids":[]},{"id":"265","name":"A11 Bungalow","short_name":"A11","group_id":"3","pixel_x":"2074","pixel_y":"2885","parent_id":"0","parent_rel":"","description":"A-Type Bungalow","lat":"0","long":"0","child_ids":[]},{"id":"266","name":"A12 Bungalow","short_name":"A12","group_id":"3","pixel_x":"2157","pixel_y":"2855","parent_id":"0","parent_rel":"","description":"A-Type Bungalow","lat":"0","long":"0","child_ids":[]},{"id":"267","name":"A13 Bungalow","short_name":"A13","group_id":"3","pixel_x":"2536","pixel_y":"2374","parent_id":"0","parent_rel":"","description":"A-Type Bungalow","lat":"0","long":"0","child_ids":[]},{"id":"268","name":"A14 Bungalow","short_name":"A14","group_id":"3","pixel_x":"3950","pixel_y":"1273","parent_id":"0","parent_rel":"","description":"A-Type Bungalow","lat":"0","long":"0","child_ids":[]},{"id":"269","name":"A15 Bungalow","short_name":"A15","group_id":"3","pixel_x":"4017","pixel_y":"1243","parent_id":"0","parent_rel":"","description":"A-Type Bungalow","lat":"0","long":"0","child_ids":[]},{"id":"270","name":"A16 Bungalow","short_name":"A16","group_id":"3","pixel_x":"4085","pixel_y":"1210","parent_id":"0","parent_rel":"","description":"A-Type Bungalow","lat":"0","long":"0","child_ids":[]},{"id":"271","name":"A17 Bungalow","short_name":"A17","group_id":"3","pixel_x":"4155","pixel_y":"1175","parent_id":"0","parent_rel":"","description":"A-Type Bungalow","lat":"0","long":"0","child_ids":[]},{"id":"272","name":"A18 Bungalow","short_name":"A18","group_id":"3","pixel_x":"4220","pixel_y":"1142","parent_id":"0","parent_rel":"","description":"A-Type Bungalow","lat":"0","long":"0","child_ids":[]},{"id":"273","name":"A19 Bungalow","short_name":"A19","group_id":"3","pixel_x":"4280","pixel_y":"1110","parent_id":"0","parent_rel":"","description":"A-Type Bungalow","lat":"0","long":"0","child_ids":[]},{"id":"274","name":"B1","short_name":"0","group_id":"3","pixel_x":"2680","pixel_y":"2368","parent_id":"0","parent_rel":"","description":"B-Type Quarters Flat nos. 1 - 6","lat":"0","long":"0","child_ids":[]},{"id":"275","name":"B2","short_name":"0","group_id":"3","pixel_x":"2848","pixel_y":"2685","parent_id":"0","parent_rel":"","description":"B-Type Quarters Flat nos. 7 - 10","lat":"0","long":"0","child_ids":[]},{"id":"276","name":"B3","short_name":"0","group_id":"3","pixel_x":"2797","pixel_y":"2820","parent_id":"0","parent_rel":"","description":"B-Type Quarters Flat nos. 11 - 14","lat":"0","long":"0","child_ids":[]},{"id":"277","name":"B4","short_name":"0","group_id":"3","pixel_x":"2743","pixel_y":"2947","parent_id":"0","parent_rel":"","description":"B-Type Quarters Flat nos. 15 - 18","lat":"0","long":"0","child_ids":[]},{"id":"278","name":"B5","short_name":"0","group_id":"3","pixel_x":"2687","pixel_y":"3079","parent_id":"0","parent_rel":"","description":"B-Type Quarters Flat nos. 19 - 22","lat":"0","long":"0","child_ids":[]},{"id":"279","name":"B6","short_name":"0","group_id":"3","pixel_x":"2508","pixel_y":"3189","parent_id":"0","parent_rel":"","description":"B-Type Quarters Flat nos. 23 - 26","lat":"0","long":"0","child_ids":[]},{"id":"280","name":"B7","short_name":"0","group_id":"3","pixel_x":"2529","pixel_y":"3009","parent_id":"0","parent_rel":"","description":"B-Type Quarters Flat nos. 27 - 30","lat":"0","long":"0","child_ids":[]},{"id":"281","name":"B8","short_name":"0","group_id":"3","pixel_x":"2600","pixel_y":"2867","parent_id":"0","parent_rel":"","description":"B-Type Quarters Flat nos. 31 - 34","lat":"0","long":"0","child_ids":[]},{"id":"282","name":"B9","short_name":"0","group_id":"3","pixel_x":"2653","pixel_y":"2748","parent_id":"0","parent_rel":"","description":"B-Type Quarters Flat nos. 35 - 38","lat":"0","long":"0","child_ids":[]},{"id":"283","name":"B10","short_name":"0","group_id":"3","pixel_x":"2726","pixel_y":"2634","parent_id":"0","parent_rel":"","description":"B-Type Quarters Flat nos. 39 - 42","lat":"0","long":"0","child_ids":[]},{"id":"284","name":"B11","short_name":"0","group_id":"3","pixel_x":"2232","pixel_y":"2552","parent_id":"0","parent_rel":"","description":"B-Type Quarters Flat nos. 43 - 46","lat":"0","long":"0","child_ids":[]},{"id":"285","name":"B12","short_name":"0","group_id":"3","pixel_x":"2080","pixel_y":"2631","parent_id":"0","parent_rel":"","description":"B-Type Quarters Flat nos. 47 - 50","lat":"0","long":"0","child_ids":[]},{"id":"286","name":"B13","short_name":"0","group_id":"3","pixel_x":"2356","pixel_y":"2478","parent_id":"0","parent_rel":"","description":"B-Type Quarters Flat nos. 51 - 54","lat":"0","long":"0","child_ids":[]},{"id":"287","name":"B14","short_name":"0","group_id":"3","pixel_x":"2470","pixel_y":"2291","parent_id":"0","parent_rel":"","description":"B-Type Quarters Flat nos. 55 - 58","lat":"0","long":"0","child_ids":[]},{"id":"288","name":"B15","short_name":"0","group_id":"3","pixel_x":"2192","pixel_y":"2665","parent_id":"0","parent_rel":"","description":"B-Type Quarters Flat nos. 59 - 62","lat":"0","long":"0","child_ids":[]},{"id":"289","name":"B16","short_name":"0","group_id":"3","pixel_x":"2085","pixel_y":"2719","parent_id":"0","parent_rel":"","description":"B-Type Quarters Flat nos. 63 - 66","lat":"0","long":"0","child_ids":[]},{"id":"290","name":"B17","short_name":"0","group_id":"3","pixel_x":"3040","pixel_y":"2461","parent_id":"0","parent_rel":"","description":"B-Type Quarters Flat nos. 67 - 72","lat":"0","long":"0","child_ids":[]},{"id":"291","name":"B18","short_name":"0","group_id":"3","pixel_x":"3159","pixel_y":"2368","parent_id":"0","parent_rel":"","description":"B-Type Quarters Flat nos. 73 - 74 and 73A - 74A ","lat":"0","long":"0","child_ids":[]},{"id":"292","name":null,"short_name":"BTR A & B","group_id":"3","pixel_x":"2002","pixel_y":"3087","parent_id":"0","parent_rel":"","description":"BTR Quarters","lat":"0","long":"0","child_ids":[]},{"id":"293","name":"C2","short_name":"0","group_id":"3","pixel_x":"3108","pixel_y":"2552","parent_id":"0","parent_rel":"","description":"C-Type Quarters Flat nos. 13 - 18","lat":"0","long":"0","child_ids":[]},{"id":"294","name":"C5","short_name":"0","group_id":"3","pixel_x":"3464","pixel_y":"2708","parent_id":"0","parent_rel":"","description":"C-Type Quarters Flat nos. 31 - 36","lat":"0","long":"0","child_ids":[]},{"id":"295","name":"C6","short_name":"0","group_id":"3","pixel_x":"3547","pixel_y":"2771","parent_id":"0","parent_rel":"","description":"C-Type Quarters Flat nos. 37 - 42","lat":"0","long":"0","child_ids":[]},{"id":"296","name":"C7","short_name":"0","group_id":"3","pixel_x":"3440","pixel_y":"2787","parent_id":"0","parent_rel":"","description":"C-Type Quarters Flat nos. 43 - 48","lat":"0","long":"0","child_ids":[]},{"id":"297","name":"C8","short_name":"0","group_id":"3","pixel_x":"3078","pixel_y":"2878","parent_id":"0","parent_rel":"","description":"C-Type Quarters Flat nos. 49 - 54","lat":"0","long":"0","child_ids":[]},{"id":"298","name":"C9","short_name":"0","group_id":"3","pixel_x":"2904","pixel_y":"2910","parent_id":"0","parent_rel":"","description":"C-Type Quarters Flat nos. 55 - 60","lat":"0","long":"0","child_ids":[]},{"id":"299","name":"C10","short_name":"0","group_id":"3","pixel_x":"2944","pixel_y":"2820","parent_id":"0","parent_rel":"","description":"C-Type Quarters Flat nos. 61 - 66","lat":"0","long":"0","child_ids":[]},{"id":"300","name":"C11","short_name":"0","group_id":"3","pixel_x":"2832","pixel_y":"3131","parent_id":"0","parent_rel":"","description":"C-Type Quarters Flat nos. 67 - 72","lat":"0","long":"0","child_ids":[]},{"id":"301","name":"C12","short_name":"0","group_id":"3","pixel_x":"2867","pixel_y":"3006","parent_id":"0","parent_rel":"","description":"C-Type Quarters Flat nos. 73 - 78","lat":"0","long":"0","child_ids":[]},{"id":"302","name":"C13","short_name":"0","group_id":"3","pixel_x":"2974","pixel_y":"3070","parent_id":"0","parent_rel":"","description":"C-Type Quarters Flat nos. 79 - 84","lat":"0","long":"0","child_ids":[]},{"id":"303","name":"C14","short_name":"0","group_id":"3","pixel_x":"3140","pixel_y":"3047","parent_id":"0","parent_rel":"","description":"C-Type Quarters Flat nos. 85 - 90","lat":"0","long":"0","child_ids":[]},{"id":"304","name":"C15","short_name":"0","group_id":"3","pixel_x":"3360","pixel_y":"3033","parent_id":"0","parent_rel":"","description":"C-Type Quarters Flat nos. 91 - 96","lat":"0","long":"0","child_ids":[]},{"id":"305","name":"C16","short_name":"0","group_id":"3","pixel_x":"3162","pixel_y":"2991","parent_id":"0","parent_rel":"","description":"C-Type Quarters Flat nos. 97 - 102","lat":"0","long":"0","child_ids":[]},{"id":"306","name":"C17","short_name":"0","group_id":"3","pixel_x":"3453","pixel_y":"2987","parent_id":"0","parent_rel":"","description":"C-Type Quarters Flat nos. 103 - 108","lat":"0","long":"0","child_ids":[]},{"id":"307","name":"C18","short_name":"0","group_id":"3","pixel_x":"3537","pixel_y":"2963","parent_id":"0","parent_rel":"","description":"C-Type Quarters Flat nos. 109 - 114","lat":"0","long":"0","child_ids":[]},{"id":"308","name":"CSRE A","short_name":"0","group_id":"3","pixel_x":"4275","pixel_y":"1177","parent_id":"0","parent_rel":"","description":"CSRE Quarters C139, C140, C143. C144. C147, C148","lat":"0","long":"0","child_ids":[]},{"id":"309","name":"CTR 19","short_name":"0","group_id":"3","pixel_x":"1815","pixel_y":"3040","parent_id":"0","parent_rel":"","description":"CTR Quarters Flat nos. 115 - 126","lat":"0","long":"0","child_ids":[]},{"id":"310","name":"CTR 20","short_name":"0","group_id":"3","pixel_x":"1749","pixel_y":"2959","parent_id":"0","parent_rel":"","description":"CTR Quarters Flat nos. 127 - 138","lat":"0","long":"0","child_ids":[]},{"id":"311","name":"H1 1","short_name":"0","group_id":"3","pixel_x":"866","pixel_y":"2684","parent_id":"0","parent_rel":"","description":"H1 Type Quarters Flat nos. 1 - 12","lat":"0","long":"0","child_ids":[]},{"id":"312","name":"H1 2","short_name":"0","group_id":"3","pixel_x":"910","pixel_y":"2613","parent_id":"0","parent_rel":"","description":"H1 Type Quarters Flat nos. 13 - 24","lat":"0","long":"0","child_ids":[]},{"id":"313","name":"H1 3","short_name":"0","group_id":"3","pixel_x":"867","pixel_y":"2575","parent_id":"0","parent_rel":"","description":"H1 Type Quarters Flat nos. 25 - 36","lat":"0","long":"0","child_ids":[]},{"id":"314","name":"H1 4","short_name":"0","group_id":"3","pixel_x":"812","pixel_y":"2560","parent_id":"0","parent_rel":"","description":"H1 Type Quarters Flat nos. 37 - 48","lat":"0","long":"0","child_ids":[]},{"id":"315","name":"H1 5","short_name":"0","group_id":"3","pixel_x":"4552","pixel_y":"1173","parent_id":"0","parent_rel":"","description":"H1 Type Quarters Flat nos. 49 - 60","lat":"0","long":"0","child_ids":[]},{"id":"316","name":"H1 6","short_name":"0","group_id":"3","pixel_x":"4468","pixel_y":"1189","parent_id":"0","parent_rel":"","description":"H1 Type Quarters Flat nos. 61 - 72","lat":"0","long":"0","child_ids":[]},{"id":"317","name":"H1 7","short_name":"0","group_id":"3","pixel_x":"4542","pixel_y":"1238","parent_id":"0","parent_rel":"","description":"H1 Type Quarters Flat nos. 73 - 84","lat":"0","long":"0","child_ids":[]},{"id":"318","name":"H1 8","short_name":"0","group_id":"3","pixel_x":"4442","pixel_y":"1239","parent_id":"0","parent_rel":"","description":"H1 Type Quarters Flat nos. 85 - 96","lat":"0","long":"0","child_ids":[]},{"id":"319","name":"H1 9","short_name":"0","group_id":"3","pixel_x":"640","pixel_y":"2329","parent_id":"0","parent_rel":"","description":"H1 Type Quarters Flat nos. 97 - 108","lat":"0","long":"0","child_ids":[]},{"id":"320","name":"H1 10","short_name":"0","group_id":"3","pixel_x":"703","pixel_y":"2275","parent_id":"0","parent_rel":"","description":"H1 Type Quarters Flat nos. 109 - 120","lat":"0","long":"0","child_ids":[]},{"id":"321","name":"H1 11","short_name":"0","group_id":"3","pixel_x":"849","pixel_y":"2249","parent_id":"0","parent_rel":"","description":"H1 Type Quarters Flat nos. 121 - 134","lat":"0","long":"0","child_ids":[]},{"id":"322","name":"H1 12","short_name":"0","group_id":"3","pixel_x":"4747","pixel_y":"1173","parent_id":"0","parent_rel":"","description":"H1 Type Quarters Flat nos. 135 - 151","lat":"0","long":"0","child_ids":[]},{"id":"323","name":"H1 13","short_name":"0","group_id":"3","pixel_x":"4786","pixel_y":"1218","parent_id":"0","parent_rel":"","description":"H1 Type Quarters Flat nos. 152 - 168","lat":"0","long":"0","child_ids":[]},{"id":"324","name":"H1 14","short_name":"0","group_id":"3","pixel_x":"4645","pixel_y":"1407","parent_id":"0","parent_rel":"","description":"H1 Type Quarters Flat nos. 169 - 176 and 1A - 2A","lat":"0","long":"0","child_ids":[]},{"id":"325","name":"H1 BB","short_name":"0","group_id":"3","pixel_x":"921","pixel_y":"2122","parent_id":"0","parent_rel":"","description":"H1 BB Type Quarters Flat nos. 1 - 26","lat":"0","long":"0","child_ids":[]},{"id":"326","name":"H2 1","short_name":"0","group_id":"3","pixel_x":"1257","pixel_y":"2812","parent_id":"0","parent_rel":"","description":"H2 Type Quarters Flat nos. 1 - 8","lat":"0","long":"0","child_ids":[]},{"id":"327","name":"H2 2","short_name":"0","group_id":"3","pixel_x":"1344","pixel_y":"2832","parent_id":"0","parent_rel":"","description":"H2 Type Quarters Flat nos. 9 - 16","lat":"0","long":"0","child_ids":[]},{"id":"328","name":"H2 3","short_name":"0","group_id":"3","pixel_x":"1417","pixel_y":"2797","parent_id":"0","parent_rel":"","description":"H2 Type Quarters Flat nos. 17 - 24","lat":"0","long":"0","child_ids":[]},{"id":"329","name":"H2 4","short_name":"0","group_id":"3","pixel_x":"1187","pixel_y":"2785","parent_id":"0","parent_rel":"","description":"H2 Type Quarters Flat nos. 25 - 32","lat":"0","long":"0","child_ids":[]},{"id":"330","name":"H2 5","short_name":"0","group_id":"3","pixel_x":"1302","pixel_y":"2738","parent_id":"0","parent_rel":"","description":"H2 Type Quarters Flat nos. 33 - 40","lat":"0","long":"0","child_ids":[]},{"id":"331","name":"H2 6","short_name":"0","group_id":"3","pixel_x":"1101","pixel_y":"2774","parent_id":"0","parent_rel":"","description":"H2 Type Quarters Flat nos. 41 - 48","lat":"0","long":"0","child_ids":[]},{"id":"332","name":"H2 7","short_name":"0","group_id":"3","pixel_x":"1211","pixel_y":"2702","parent_id":"0","parent_rel":"","description":"H2 Type Quarters Flat nos. 49 - 56","lat":"0","long":"0","child_ids":[]},{"id":"333","name":"H2 8","short_name":"0","group_id":"3","pixel_x":"1059","pixel_y":"2719","parent_id":"0","parent_rel":"","description":"H2 Type Quarters Flat nos. 57 - 64","lat":"0","long":"0","child_ids":[]},{"id":"334","name":"H2 9","short_name":"0","group_id":"3","pixel_x":"1145","pixel_y":"2682","parent_id":"0","parent_rel":"","description":"H2 Type Quarters Flat nos. 65 - 72","lat":"0","long":"0","child_ids":[]},{"id":"335","name":"H2 10","short_name":"0","group_id":"3","pixel_x":"978","pixel_y":"2702","parent_id":"0","parent_rel":"","description":"H2 Type Quarters Flat nos. 73 - 80","lat":"0","long":"0","child_ids":[]},{"id":"336","name":"H2 11","short_name":"0","group_id":"3","pixel_x":"1049","pixel_y":"2666","parent_id":"0","parent_rel":"","description":"H2 Type Quarters Flat nos. 81 - 88","lat":"0","long":"0","child_ids":[]},{"id":"337","name":"H2 12","short_name":"0","group_id":"3","pixel_x":"960","pixel_y":"2640","parent_id":"0","parent_rel":"","description":"H2 Type Quarters Flat nos. 89 - 96","lat":"0","long":"0","child_ids":[]},{"id":"338","name":"H2 13","short_name":"0","group_id":"3","pixel_x":"753","pixel_y":"2520","parent_id":"0","parent_rel":"","description":"H2 Type Quarters Flat nos. 97 - 104","lat":"0","long":"0","child_ids":[]},{"id":"339","name":"H2 14","short_name":"0","group_id":"3","pixel_x":"717","pixel_y":"2510","parent_id":"0","parent_rel":"","description":"H2 Type Quarters Flat nos. 105 - 112","lat":"0","long":"0","child_ids":[]},{"id":"340","name":"H2 15","short_name":"0","group_id":"3","pixel_x":"695","pixel_y":"2461","parent_id":"0","parent_rel":"","description":"H2 Type Quarters Flat nos. 113 - 120","lat":"0","long":"0","child_ids":[]},{"id":"341","name":"H2 16","short_name":"0","group_id":"3","pixel_x":"774","pixel_y":"2412","parent_id":"0","parent_rel":"","description":"H2 Type Quarters Flat nos. 121 - 128","lat":"0","long":"0","child_ids":[]},{"id":"342","name":"H2 17","short_name":"0","group_id":"3","pixel_x":"3110","pixel_y":"1832","parent_id":"0","parent_rel":"","description":"H2 Type Quarters Flat nos. 129 - 136","lat":"0","long":"0","child_ids":[]},{"id":"343","name":"H2 18","short_name":"0","group_id":"3","pixel_x":"4451","pixel_y":"1320","parent_id":"0","parent_rel":"","description":"H2 Type Quarters Flat nos. 137 - 144","lat":"0","long":"0","child_ids":[]},{"id":"344","name":"H2 19","short_name":"0","group_id":"3","pixel_x":"4377","pixel_y":"1329","parent_id":"0","parent_rel":"","description":"H2 Type Quarters Flat nos. 145 - 152","lat":"0","long":"0","child_ids":[]},{"id":"345","name":"H2 20","short_name":"0","group_id":"3","pixel_x":"4307","pixel_y":"1320","parent_id":"0","parent_rel":"","description":"H2 Type Quarters Flat nos. 153 - 160","lat":"0","long":"0","child_ids":[]},{"id":"346","name":"H2 21","short_name":"0","group_id":"3","pixel_x":"4304","pixel_y":"1260","parent_id":"0","parent_rel":"","description":"H2 Type Quarters Flat nos. 161 - 168","lat":"0","long":"0","child_ids":[]},{"id":"347","name":"H2 22","short_name":"0","group_id":"3","pixel_x":"4231","pixel_y":"1259","parent_id":"0","parent_rel":"","description":"H2 Type Quarters Flat nos. 169 - 176","lat":"0","long":"0","child_ids":[]},{"id":"348","name":"H2 24","short_name":"0","group_id":"3","pixel_x":"522","pixel_y":"2424","parent_id":"0","parent_rel":"","description":"H2 Type Quarters Flat nos. 185 - 192","lat":"0","long":"0","child_ids":[]},{"id":"349","name":"H2 25","short_name":"0","group_id":"3","pixel_x":"568","pixel_y":"2377","parent_id":"0","parent_rel":"","description":"H2 Type Quarters Flat nos. 193 - 200","lat":"0","long":"0","child_ids":[]},{"id":"350","name":"H2 26","short_name":"0","group_id":"3","pixel_x":"746","pixel_y":"2246","parent_id":"0","parent_rel":"","description":"H2 Type Quarters Flat nos. 201 - 208","lat":"0","long":"0","child_ids":[]},{"id":"351","name":"H2 27","short_name":"0","group_id":"3","pixel_x":"793","pixel_y":"2214","parent_id":"0","parent_rel":"","description":"H2 Type Quarters Flat nos. 209 - 216","lat":"0","long":"0","child_ids":[]},{"id":"352","name":"H2 28","short_name":"0","group_id":"3","pixel_x":"4193","pixel_y":"1295","parent_id":"0","parent_rel":"","description":"H2 Type Quarters Flat nos. 217 - 232","lat":"0","long":"0","child_ids":[]},{"id":"353","name":"H2 29","short_name":"0","group_id":"3","pixel_x":"691","pixel_y":"2410","parent_id":"0","parent_rel":"","description":"H2 Type Quarters Flat nos. 233 - 248","lat":"0","long":"0","child_ids":[]},{"id":"354","name":"H2 BB","short_name":"0","group_id":"3","pixel_x":"840","pixel_y":"2180","parent_id":"0","parent_rel":"","description":"H2 BB Type Quarters Flat nos. 1 - 18","lat":"0","long":"0","child_ids":[]},{"id":"355","name":"KV 1","short_name":"0","group_id":"3","pixel_x":"3592","pixel_y":"2817","parent_id":"0","parent_rel":"","description":"KV Quarters 1 - 5","lat":"0","long":"0","child_ids":[]},{"id":"356","name":"KV 2","short_name":"0","group_id":"3","pixel_x":"3498","pixel_y":"2854","parent_id":"0","parent_rel":"","description":"KV Quarters 6 - 11","lat":"0","long":"0","child_ids":[]},{"id":"357","name":"MW 1","short_name":"0","group_id":"3","pixel_x":"4267","pixel_y":"752","parent_id":"0","parent_rel":"","description":"MW Quarters 1 - 32","lat":"0","long":"0","child_ids":[]},{"id":"358","name":"MW 2","short_name":"0","group_id":"3","pixel_x":"4124","pixel_y":"780","parent_id":"0","parent_rel":"","description":"MW Quarters 33 - 68","lat":"0","long":"0","child_ids":[]},{"id":"359","name":"Type1 1","short_name":"0","group_id":"3","pixel_x":"4113","pixel_y":"2583","parent_id":"0","parent_rel":"","description":"Type 1 Quarters Flat nos. 1 - 12","lat":"0","long":"0","child_ids":[]},{"id":"360","name":"Type1 2","short_name":"0","group_id":"3","pixel_x":"4214","pixel_y":"2586","parent_id":"0","parent_rel":"","description":"Type 1 Quarters Flat nos. 13 - 24","lat":"0","long":"0","child_ids":[]},{"id":"361","name":"Type1 3","short_name":"0","group_id":"3","pixel_x":"4177","pixel_y":"2652","parent_id":"0","parent_rel":"","description":"Type 1 Quarters Flat nos. 25 - 36","lat":"0","long":"0","child_ids":[]},{"id":"362","name":"Type1 4","short_name":"0","group_id":"3","pixel_x":"4067","pixel_y":"2658","parent_id":"0","parent_rel":"","description":"Type 1 Quarters Flat nos. 37 - 48","lat":"0","long":"0","child_ids":[]},{"id":"363","name":"Type1 6","short_name":"0","group_id":"3","pixel_x":"4660","pixel_y":"1367","parent_id":"0","parent_rel":"","description":"Type 1 Quarters Flat nos. 61 - 72","lat":"0","long":"0","child_ids":[]},{"id":"364","name":"Type1 7","short_name":"0","group_id":"3","pixel_x":"4600","pixel_y":"1351","parent_id":"0","parent_rel":"","description":"Type 1 Quarters Flat nos. 73 - 84","lat":"0","long":"0","child_ids":[]},{"id":"365","name":"Type1 8","short_name":"0","group_id":"3","pixel_x":"4616","pixel_y":"1271","parent_id":"0","parent_rel":"","description":"Type 1 Quarters Flat nos. 85 - 96","lat":"0","long":"0","child_ids":[]},{"id":"366","name":"Type1 9","short_name":"0","group_id":"3","pixel_x":"4675","pixel_y":"1293","parent_id":"0","parent_rel":"","description":"Type 1 Quarters Flat nos. 97 - 108","lat":"0","long":"0","child_ids":[]},{"id":"367","name":"Type1 10","short_name":"0","group_id":"3","pixel_x":"4373","pixel_y":"758","parent_id":"0","parent_rel":"","description":"Type 1 Quarters Flat nos. 109 - 120","lat":"0","long":"0","child_ids":[]},{"id":"368","name":"Type1 11","short_name":"0","group_id":"3","pixel_x":"3354","pixel_y":"812","parent_id":"0","parent_rel":"","description":"Type 1 Quarters Flat nos. 121 - 132","lat":"0","long":"0","child_ids":[]},{"id":"369","name":"Type1 13","short_name":"0","group_id":"3","pixel_x":"4637","pixel_y":"1237","parent_id":"0","parent_rel":"","description":"Type 1 Quarters Flat nos. 145 - 156","lat":"0","long":"0","child_ids":[]},{"id":"370","name":"Type1 14","short_name":"0","group_id":"3","pixel_x":"4670","pixel_y":"1198","parent_id":"0","parent_rel":"","description":"Type 1 Quarters Flat nos. 157 - 168","lat":"0","long":"0","child_ids":[]},{"id":"371","name":"Type1 15","short_name":"0","group_id":"3","pixel_x":"3151","pixel_y":"1798","parent_id":"0","parent_rel":"","description":"Type 1 Quarters Flat nos. 169 - 180","lat":"0","long":"0","child_ids":[]},{"id":"372","name":"Type1 16","short_name":"0","group_id":"3","pixel_x":"4713","pixel_y":"1252","parent_id":"0","parent_rel":"","description":"Type 1 Quarters Flat nos. 181 - 192","lat":"0","long":"0","child_ids":[]},{"id":"373","name":"Type1 17","short_name":"0","group_id":"3","pixel_x":"4785","pixel_y":"1290","parent_id":"0","parent_rel":"","description":"Type 1 Quarters Flat nos. 193 - 208","lat":"0","long":"0","child_ids":[]},{"id":"374","name":"Type1 18","short_name":"0","group_id":"3","pixel_x":"4801","pixel_y":"1269","parent_id":"0","parent_rel":"","description":"Type 1 Quarters Flat nos. 209 - 224","lat":"0","long":"0","child_ids":[]},{"id":"375","name":"Type1 19","short_name":"0","group_id":"3","pixel_x":"4340","pixel_y":"815","parent_id":"0","parent_rel":"","description":"Type 1 Quarters Flat nos. 225 - 259","lat":"0","long":"0","child_ids":[]},{"id":"376","name":"Type1 20","short_name":"0","group_id":"3","pixel_x":"4328","pixel_y":"871","parent_id":"0","parent_rel":"","description":"Type 1 Quarters Flat nos. 260 - 289","lat":"0","long":"0","child_ids":[]},{"id":"377","name":"Type1 21","short_name":"0","group_id":"3","pixel_x":"4521","pixel_y":"1346","parent_id":"0","parent_rel":"","description":"Type 1 Quarters Flat nos. 290 - 309","lat":"0","long":"0","child_ids":[]},{"id":"378","name":"Type1 22","short_name":"0","group_id":"3","pixel_x":"2565","pixel_y":"680","parent_id":"0","parent_rel":"","description":"Type 1 Quarters Flat nos. 310 - 321","lat":"0","long":"0","child_ids":[]},{"id":"379","name":"QIP 1","short_name":"0","group_id":"3","pixel_x":"4830","pixel_y":"1376","parent_id":"0","parent_rel":"","description":"QIP Quarters Flat nos. 1 - 16","lat":"0","long":"0","child_ids":[]},{"id":"380","name":"QIP 2","short_name":"0","group_id":"3","pixel_x":"4869","pixel_y":"1328","parent_id":"0","parent_rel":"","description":"QIP Quarters Flat nos. 17 - 35","lat":"0","long":"0","child_ids":[]},{"id":"381","name":"CSRE B","short_name":"0","group_id":"3","pixel_x":"4275","pixel_y":"1177","parent_id":"0","parent_rel":"","description":"CSRE Quarters C141, C142, C145, C146, C149, C150","lat":"0","long":"0","child_ids":[]},{"id":"382","name":"CSRE C","short_name":"0","group_id":"3","pixel_x":"4275","pixel_y":"1177","parent_id":"0","parent_rel":"","description":"CSRE Quarters D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12","lat":"0","long":"0","child_ids":[]},{"id":"384","name":"LT 003 (LCT 03)","short_name":"0","group_id":"4","pixel_x":"3570","pixel_y":"2152","parent_id":"59","parent_rel":"Ground floor","description":"","lat":"0","long":"0","child_ids":[]}]
\ No newline at end of file
package app.insti.fragment; package app.insti.fragment;
import android.Manifest;
import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.res.Configuration;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.content.res.ColorStateList;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.PorterDuff; import android.graphics.PointF;
import android.location.Location; import android.graphics.Typeface;
import android.location.LocationManager; import android.graphics.drawable.ColorDrawable;
import android.os.Build; import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Bundle; import android.os.Bundle;
import android.support.design.widget.FloatingActionButton; import android.os.Handler;
import android.support.v4.app.ActivityCompat; import android.os.Message;
import android.support.v4.content.ContextCompat; import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.SpannableStringBuilder;
import android.text.TextPaint;
import android.text.TextWatcher;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.text.style.StyleSpan;
import android.text.util.Linkify;
import android.util.Log; import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ExpandableListView;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult; import com.mrane.campusmap.ExpandableListAdapter;
import com.google.android.gms.common.api.GoogleApiClient; import com.mrane.campusmap.FuzzySearchAdapter;
import com.google.android.gms.common.api.PendingResult; import com.mrane.campusmap.IndexFragment;
import com.google.android.gms.common.api.ResultCallback; import com.mrane.campusmap.ListFragment;
import com.google.android.gms.common.api.Status; import com.mrane.campusmap.SettingsManager;
import com.google.android.gms.location.LocationListener; import com.mrane.data.Building;
import com.google.android.gms.location.LocationRequest; import com.mrane.data.Locations;
import com.google.android.gms.location.LocationServices; import com.mrane.data.Room;
import com.google.android.gms.location.LocationSettingsRequest; import com.mrane.navigation.CardSlideListener;
import com.google.android.gms.location.LocationSettingsResult; import com.mrane.navigation.SlidingUpPanelLayout;
import com.google.android.gms.location.LocationSettingsStates; import com.mrane.zoomview.CampusMapView;
import com.google.android.gms.location.LocationSettingsStatusCodes; import com.mrane.zoomview.SubsamplingScaleImageView;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory; import java.util.ArrayList;
import com.google.android.gms.maps.GoogleMap; import java.util.HashMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.regex.Pattern;
import app.insti.Constants;
import app.insti.R; import app.insti.R;
import static android.content.Context.LOCATION_SERVICE; public class MapFragment extends Fragment implements TextWatcher,
TextView.OnEditorActionListener, AdapterView.OnItemClickListener, View.OnFocusChangeListener,
View.OnTouchListener, ExpandableListView.OnChildClickListener {
private static MapFragment mainactivity;
private SettingsManager settingsManager;
private FuzzySearchAdapter adapter;
private ExpandableListAdapter expAdapter;
private FragmentManager fragmentManager;
private ListFragment listFragment;
private IndexFragment indexFragment;
private Fragment fragment;
public LinearLayout newSmallCard;
public ImageView placeColor;
private RelativeLayout fragmentContainer;
private View actionBarView;
public TextView placeNameTextView;
public TextView placeSubHeadTextView;
public EditText editText;
public HashMap<String, com.mrane.data.Marker> data;
private List<com.mrane.data.Marker> markerlist;
public FragmentTransaction transaction;
public CampusMapView campusMapView;
public ImageButton removeIcon;
public ImageButton indexIcon;
public ImageButton mapIcon;
public ImageButton addMarkerIcon;
private DrawerLayout mDrawerLayout;
private ActionBarDrawerToggle mDrawerToggle;
private SlidingUpPanelLayout slidingLayout;
private CardSlideListener cardSlideListener;
private boolean noFragments = true;
private boolean editTextFocused = false;
private final String firstStackTag = "FIRST_TAG";
private final int MSG_ANIMATE = 1;
private final int MSG_PLAY_SOUND = 2;
private final int MSG_DISPLAY_MAP = 3;
private final long DELAY_ANIMATE = 150;
private final long DELAY_INIT_LAYOUT = 250;
private Toast toast;
private String message = "Sorry, no such place in our data.";
private static final String JSONUrl = "http://home.iitb.ac.in/~madhu.kiran/data.json";
private static final String JSONFILE = "data.json";
public static final PointF MAP_CENTER = new PointF(2971f, 1744f);
public static final long DURATION_INIT_MAP_ANIM = 500;
public static final String FONT_SEMIBOLD = "rigascreen_bold.ttf";
public static final String FONT_REGULAR = "rigascreen_regular.ttf";
public static final String FONT_LIGHT = "roboto_light.ttf";
public static final int SOUND_ID_RESULT = 0;
public static final int SOUND_ID_ADD = 1;
public static final int SOUND_ID_REMOVE = 2;
public SoundPool soundPool;
public int[] soundPoolIds;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_ANIMATE:
showResultOnMap((String) msg.obj);
break;
case MSG_PLAY_SOUND:
playAnimSound(msg.arg1);
break;
case MSG_DISPLAY_MAP:
displayMap();
break;
}
}
};
public class MapFragment extends BaseFragment implements OnMapReadyCallback, LocationListener, public MapFragment() {
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener { // Required empty public constructor
}
SupportMapFragment gMapFragment; @Override
GoogleMap googleMap; public void onCreate(Bundle savedInstanceState) {
GoogleApiClient mGoogleApiClient; mainactivity = this;
Location mLastLocation; super.onCreate(savedInstanceState);
Marker mCurrLocationMarker; }
LocationRequest mLocationRequest;
private FloatingActionButton locationButton;
private Location currentLocation;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
// Inflate the layout for this fragment // Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_map, container, false); return inflater.inflate(R.layout.fragment_map, container, false);
gMapFragment = (SupportMapFragment) this.getChildFragmentManager().findFragmentById(R.id.viewMap);
gMapFragment.getMapAsync(this);
return view;
} }
@Override @Override
public void onStart() { public void onStart() {
super.onStart(); super.onStart();
// setContentView(R.layout.activity_main);
// setUpActionBar();
setUpDrawer();
newSmallCard = (LinearLayout) getActivity().findViewById(R.id.new_small_card);
slidingLayout = (SlidingUpPanelLayout) getActivity().findViewById(R.id.sliding_layout);
placeNameTextView = (TextView) getActivity().findViewById(R.id.place_name);
placeColor = (ImageView) getActivity().findViewById(R.id.place_color);
placeSubHeadTextView = (TextView) getActivity().findViewById(R.id.place_sub_head);
cardSlideListener = new CardSlideListener(this);
slidingLayout.setPanelSlideListener(cardSlideListener);
slidingLayout.post(setAnchor());
Locations mLocations = new Locations(getContext());
data = mLocations.data;
markerlist = new ArrayList<com.mrane.data.Marker>(data.values());
initShowDefault();
initImageUri();
fragmentContainer = (RelativeLayout) getActivity().findViewById(R.id.fragment_container);
Toolbar toolbar = getActivity().findViewById(R.id.toolbar); adapter = new FuzzySearchAdapter(getContext(), markerlist);
toolbar.setTitle("Map"); editText = (EditText)getView().findViewById(R.id.search);
editText.addTextChangedListener(this);
editText.setOnEditorActionListener(this);
editText.setOnFocusChangeListener(this);
locationButton = (FloatingActionButton) getActivity().findViewById(R.id.location_button); settingsManager = new SettingsManager(getContext());
locationButton.setImageResource(R.drawable.ic_my_location_black_24dp);
locationButton.getDrawable().setColorFilter(ContextCompat.getColor(getContext(), R.color.colorPrimaryDark), PorterDuff.Mode.SRC_IN);
locationButton.setOnClickListener(new View.OnClickListener() { campusMapView = (CampusMapView) getActivity().findViewById(R.id.campusMapView);
campusMapView.setImageAsset("map.jpg");
campusMapView.setSettingsManager(settingsManager);
campusMapView.setData(data);
removeIcon = (ImageButton) getActivity().findViewById(R.id.remove_icon);
removeIcon.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
Log.v("MapFragment", "Location button pressed"); removeClick(v);
try { }
});
LocationManager lm = (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE); indexIcon = (ImageButton) getActivity().findViewById(R.id.index_icon);
boolean gps_enabled = false; indexIcon.setOnClickListener(new View.OnClickListener() {
boolean network_enabled = false; @Override
public void onClick(View v) {
if (ActivityCompat.checkSelfPermission(getActivity(), android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getContext(), android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { indexClick(v);
ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, Constants.MY_PERMISSIONS_REQUEST_LOCATION);
return;
}
try {
gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (Exception ex) {
}
try {
network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch (Exception ex) {
}
if (!gps_enabled && !network_enabled) {
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(30 * 1000);
locationRequest.setFastestInterval(5 * 1000);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);
//**************************
builder.setAlwaysShow(true); //this is the key ingredient
//**************************
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
@Override
public void onResult(LocationSettingsResult result) {
final Status status = result.getStatus();
final LocationSettingsStates state = result.getLocationSettingsStates();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
// All location settings are satisfied. The client can initialize location
// requests here.
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. But could be fixed by showing the user
// a dialog.
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
status.startResolutionForResult(
getActivity(), 1000);
} catch (IntentSender.SendIntentException e) {
// Ignore the error.
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
// Location settings are not satisfied. However, we have no way to fix the
// settings so we won't show the dialog.
break;
}
}
});
}
currentLocation = getLastKnownLocation();
if (currentLocation != null) {
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude()), 17);
googleMap.animateCamera(cameraUpdate);
locationButton.getDrawable().setColorFilter(ContextCompat.getColor(getContext(), R.color.colorPrimary), PorterDuff.Mode.SRC_IN);
}
} catch (Exception e) {
checkLocationPermission();
Toast.makeText(getContext(), "Please turn on Location from the Settings", Toast.LENGTH_SHORT).show();
}
} }
}); });
mapIcon = (ImageButton) getActivity().findViewById(R.id.map_icon);
mapIcon.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mapClick(v);
}
});
addMarkerIcon = (ImageButton) getActivity().findViewById(R.id.add_marker_icon);
fragmentManager = getChildFragmentManager();
listFragment = new ListFragment();
indexFragment = new IndexFragment();
adapter.setSettingsManager(settingsManager);
initSoundPool();
setFonts();
toast = Toast.makeText(getContext(), message, Toast.LENGTH_LONG);
} }
private Location getLastKnownLocation() { private void setUpDrawer() {
//Create a location manager object instance Toolbar mToolbar = (Toolbar) getActivity().findViewById(R.id.toolbar);
LocationManager mLocationManager = (LocationManager) getContext().getSystemService(LOCATION_SERVICE); actionBarView = getActivity().findViewById(R.id.toolbar);
//Get all the different providers which can give current location info mDrawerLayout = (DrawerLayout) getActivity().findViewById(R.id.drawer_layout);
List<String> providers = mLocationManager.getProviders(true); mDrawerToggle = new ActionBarDrawerToggle(getActivity(),
//Initialising the location to be null mDrawerLayout,
Location bestLocation = null; mToolbar,
//Creating a for loop to go through all the location providers and get the location R.string.drawer_open,
for (String provider : providers) { R.string.drawer_close) {
TextView settingsTitle = (TextView) getActivity().findViewById(R.id.settings_title);
/** Called when a drawer has settled in a completely closed state. */
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
settingsTitle.setVisibility(View.GONE);
editText.setVisibility(View.VISIBLE);
setCorrectIcons();
}
//if permission is not granted, then get the permission /** Called when a drawer has settled in a completely open state. */
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
editText.setVisibility(View.GONE);
indexIcon.setVisibility(View.GONE);
mapIcon.setVisibility(View.GONE);
removeIcon.setVisibility(View.GONE);
settingsTitle.setVisibility(View.VISIBLE);
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
if (ContextCompat.checkSelfPermission(getContext(), android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { }
@Override
public void onConfigurationChanged(Configuration newConfig) {
// TODO Auto-generated method stub
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}
ActivityCompat.requestPermissions(getActivity(), new String[]{android.Manifest.permission.ACCESS_COARSE_LOCATION}, @Override
Constants.MY_PERMISSIONS_REQUEST_LOCATION); public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
private void initShowDefault() {
String[] keys = { "Convocation Hall", "Hostel 13 House of Titans",
"Hostel 15", "Main Gate no. 2",
"Market Gate, Y point Gate no. 3", "Lake Side Gate no. 1", };
for (String key : keys) {
if (data.containsKey(key)) {
data.get(key).setShowDefault(true);
} else {
Log.d("null point", "key not found (initShowDefault): " + key);
} }
//Get the last known location from the data provider }
Location l = mLocationManager.getLastKnownLocation(provider); }
//If the last know location provided by the data provider is null then ignore the provider and move to the next one.
if (l == null) { private void initImageUri() {
continue; String[] keys = { "Convocation Hall", "Guest House/ Jalvihar",
"Guest House/ Vanvihar", "Gulmohar Restaurant", "Hostel 14",
"Industrial Design Centre", "Main Building",
"Nestle Cafe (Coffee Shack)", "School of Management",
"Victor Menezes Convention Centre" };
String[] uri = { "convo_hall", "jalvihar", "vanvihar", "gulmohar",
"h14", "idc", "mainbuilding", "nescafestall", "som", "vmcc" };
for (int i = 0; i < keys.length; i++) {
if (data.containsKey(keys[i])) {
data.get(keys[i]).setImageUri(uri[i]);
} else {
Log.d("null point", "check " + keys[i]);
} }
}
}
if (bestLocation == null || l.getAccuracy() < bestLocation.getAccuracy()) { private void setFonts() {
bestLocation = l; Typeface regular = Typeface.createFromAsset(getActivity().getAssets(), FONT_REGULAR);
placeNameTextView.setTypeface(regular, Typeface.BOLD);
placeSubHeadTextView.setTypeface(regular);
editText.setTypeface(regular);
TextView settingsTitle = (TextView) getActivity()
.findViewById(R.id.settings_title);
settingsTitle.setTypeface(regular);
}
private Runnable setAnchor() {
Runnable runnable = new Runnable() {
@Override
public void run() {
int totalHeight = slidingLayout.getHeight();
int expandedCardHeight = getResources().getDimensionPixelSize(
R.dimen.expanded_card_height);
float anchorPoint = 0.5f;
slidingLayout.setAnchorPoint(anchorPoint);
Log.d("testing", "Anchor point = " + anchorPoint);
} }
};
return runnable;
}
private void initSoundPool() {
soundPool = new SoundPool(2, AudioManager.STREAM_MUSIC, 100);
soundPoolIds = new int[3];
soundPoolIds[SOUND_ID_RESULT] = soundPool.load(getContext(),
R.raw.result_marker, 1);
soundPoolIds[SOUND_ID_ADD] = soundPool.load(getContext(), R.raw.add_marker, 2);
soundPoolIds[SOUND_ID_REMOVE] = soundPool.load(getContext(),
R.raw.remove_marker, 3);
}
@Override
public void afterTextChanged(Editable arg0) {
String text = editText.getText().toString()
.toLowerCase(Locale.getDefault());
adapter.filter(refineText(text));
}
private String refineText(String text) {
String refinedText = text.replaceAll(Pattern.quote("("), "@")
.replaceAll(Pattern.quote(")"), "@")
.replaceAll(Pattern.quote("."), "@")
.replaceAll(Pattern.quote("+"), "@")
.replaceAll(Pattern.quote("{"), "@")
.replaceAll(Pattern.quote("?"), "@")
.replaceAll(Pattern.quote("\\"), "@")
.replaceAll(Pattern.quote("["), "@")
.replaceAll(Pattern.quote("^"), "@")
.replaceAll(Pattern.quote("$"), "@");
return refinedText;
}
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
}
@Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
this.setCorrectIcons();
}
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if ((actionId == EditorInfo.IME_ACTION_SEARCH)
|| (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) {
onItemClick(null, v, 0, 0);
}
return true;
}
public static MapFragment getMainActivity() {
return mainactivity;
}
private void putFragment(Fragment tempFragment) {
this.dismissCard();
transaction = fragmentManager.beginTransaction();
fragment = tempFragment;
if (noFragments) {
transaction.add(R.id.fragment_container, tempFragment);
transaction.addToBackStack(firstStackTag);
transaction.commit();
} else {
transaction.replace(R.id.fragment_container, tempFragment);
transaction.addToBackStack(null);
transaction.commit();
} }
return bestLocation; noFragments = false;
}
public void backToMap() {
noFragments = true;
this.hideKeyboard();
fragmentManager.popBackStack(firstStackTag,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
this.removeEditTextFocus(null);
this.setCorrectIcons();
this.displayMap();
} }
@Override @Override
public void onMapReady(GoogleMap gMap) { public void onItemClick(AdapterView<?> arg0, View arg1, int id, long arg3) {
googleMap = gMap; if (adapter.getResultSize() == 0) {
if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { toast.setText(message);
checkLocationPermission(); toast.show();
} else { } else {
googleMap.setMyLocationEnabled(true); String selection = editText.getText().toString();
googleMap.getUiSettings().setMyLocationButtonEnabled(false); if (id < adapter.getCount()) {
selection = adapter.getItem(id).getName();
}
this.hideKeyboard();
this.removeEditTextFocus(selection);
this.backToMap();
} }
locationButton.setBackgroundTintList(ColorStateList.valueOf(Color.parseColor("#FFFFFF"))); }
//Initialize Google Play Services public void displayMap() {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // check if is Image ready
if (ContextCompat.checkSelfPermission(getActivity(), if (!campusMapView.isImageReady()) {
Manifest.permission.ACCESS_FINE_LOCATION) Message msg = mHandler.obtainMessage(MSG_DISPLAY_MAP);
== PackageManager.PERMISSION_GRANTED) { mHandler.sendMessageDelayed(msg, DELAY_INIT_LAYOUT);
//Location Permission already granted } else {
buildGoogleApiClient(); // get text from auto complete text box
googleMap.setMyLocationEnabled(true); String key = editText.getText().toString();
// get Marker object if exists
com.mrane.data.Marker marker = data.get(key);
// display and zoom to marker if exists
if (marker != null) {
Message msg = mHandler.obtainMessage(MSG_ANIMATE, key);
mHandler.sendMessageDelayed(msg, DELAY_ANIMATE);
} else { } else {
//Request Location Permission campusMapView.setResultMarker(null);
checkLocationPermission(); this.dismissCard();
campusMapView.invalidate();
}
}
}
private void showResultOnMap(String key) {
com.mrane.data.Marker marker = data.get(key);
showCard(marker);
campusMapView.setAndShowResultMarker(marker);
}
public void showCard() {
com.mrane.data.Marker marker = campusMapView.getResultMarker();
showCard(marker);
}
public void showCard(com.mrane.data.Marker marker) {
String name = marker.getName();
if (!marker.getShortName().equals("0"))
name = marker.getShortName();
placeNameTextView.setText(name);
setSubHeading(marker);
setAddMarkerIcon(marker);
addDescriptionView(marker);
placeColor.setImageDrawable(new ColorDrawable(marker.getColor()));
getActivity().findViewById(R.id.place_group_color).setBackgroundColor(
marker.getColor());
reCenterMarker(marker);
cardSlideListener.showCard();
}
private void setImage(LinearLayout parent, com.mrane.data.Marker marker) {
View v = getLayoutInflater().inflate(R.layout.map_card_image, parent);
ImageView iv = (ImageView) v.findViewById(R.id.place_image);
int imageId = getResources().getIdentifier(marker.getImageUri(),
"drawable", getContext().getPackageName());
iv.setImageResource(imageId);
}
private void addDescriptionView(com.mrane.data.Marker marker) {
LinearLayout parent = (LinearLayout) getActivity().findViewById(R.id.other_details);
parent.removeAllViews();
if (!marker.getImageUri().isEmpty()) {
setImage(parent, marker);
}
if (marker instanceof Building) {
setChildrenView(parent, (Building) marker);
}
if (!marker.getDescription().isEmpty()) {
View desc = getLayoutInflater().inflate(R.layout.map_place_description,
parent);
TextView descHeader = (TextView) desc
.findViewById(R.id.desc_header);
Typeface regular = Typeface.createFromAsset(getContext().getAssets(),
FONT_REGULAR);
descHeader.setTypeface(regular, Typeface.BOLD);
TextView descContent = (TextView) desc
.findViewById(R.id.desc_content);
descContent.setTypeface(regular);
descContent.setText(getDescriptionText(marker));
Linkify.addLinks(descContent, Linkify.ALL);
descContent.setLinkTextColor(Color.rgb(19, 140, 190));
}
}
public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null)
return;
int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(),
View.MeasureSpec.UNSPECIFIED);
int totalHeight = 0;
View view = null;
for (int i = 0; i < listAdapter.getCount(); i++) {
view = listAdapter.getView(i, view, listView);
if (i == 0)
view.setLayoutParams(new ViewGroup.LayoutParams(desiredWidth,
RelativeLayout.LayoutParams.WRAP_CONTENT));
view.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
totalHeight += view.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight
+ (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
listView.requestLayout();
}
private void setChildrenView(LinearLayout parent, Building building) {
View childrenView = getLayoutInflater().inflate(R.layout.map_children_view,
parent);
View headerLayout = childrenView.findViewById(R.id.header_layout);
TextView headerName = (TextView) childrenView
.findViewById(R.id.list_header);
String headerText = "inside ";
if (building.getShortName().equals("0"))
headerText += building.getName();
else
headerText += building.getShortName();
Typeface bold = Typeface.createFromAsset(getContext().getAssets(), FONT_REGULAR);
headerName.setTypeface(bold, Typeface.BOLD);
headerName.setText(headerText);
final ImageView icon = (ImageView) childrenView
.findViewById(R.id.arrow_icon);
final ListView childrenListView = (ListView) childrenView
.findViewById(R.id.child_list);
childrenListView.setVisibility(View.GONE);
ArrayList<String> childNames = new ArrayList<String>();
for (String name : building.children) {
childNames.add(name);
}
final CustomListAdapter adapter = new CustomListAdapter(getContext(),
R.layout.map_child, childNames);
childrenListView.setAdapter(adapter);
childrenListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1,
int position, long arg3) {
String key = adapter.getItem(position);
removeEditTextFocus(key);
backToMap();
} }
});
headerLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
if (childrenListView.getVisibility() == View.VISIBLE) {
childrenListView.setVisibility(View.GONE);
icon.setImageResource(R.drawable.ic_action_next_item);
} else {
setListViewHeightBasedOnChildren(childrenListView);
childrenListView.setVisibility(View.VISIBLE);
icon.setImageResource(R.drawable.ic_action_expand);
}
}
});
}
private class CustomListAdapter extends ArrayAdapter<String> {
private Context mContext;
private int id;
private List<String> items;
public CustomListAdapter(Context context, int textViewResourceId,
List<String> list) {
super(context, textViewResourceId, list);
mContext = context;
id = textViewResourceId;
items = list;
}
@Override
public View getView(int position, View v, ViewGroup parent) {
View mView = v;
if (mView == null) {
LayoutInflater vi = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mView = vi.inflate(id, null);
}
TextView text = (TextView) mView.findViewById(R.id.child_name);
Log.d("testing", "position = " + position);
if (items.get(position) != null) {
Typeface regular = Typeface.createFromAsset(getContext().getAssets(),
FONT_REGULAR);
text.setText(items.get(position));
text.setTypeface(regular);
}
return mView;
}
}
private SpannableStringBuilder getDescriptionText(com.mrane.data.Marker marker) {
String text = marker.getDescription();
SpannableStringBuilder desc = new SpannableStringBuilder(text);
String[] toBoldParts = { "Email", "Phone No.", "Fax No." };
for (String part : toBoldParts) {
setBold(desc, part);
}
return desc;
}
private void setBold(SpannableStringBuilder text, String part) {
int start = text.toString().indexOf(part);
int end = start + part.length();
final StyleSpan bold = new StyleSpan(Typeface.BOLD);
if (start >= 0)
text.setSpan(bold, start, end,
SpannableStringBuilder.SPAN_EXCLUSIVE_EXCLUSIVE);
}
private void setSubHeading(com.mrane.data.Marker marker) {
SpannableStringBuilder result = new SpannableStringBuilder("");
result.append(marker.getName());
if (marker instanceof Room) {
Room room = (Room) marker;
String tag = room.tag;
if (!tag.equals("Inside")) {
tag += ",";
} else {
tag = "in";
}
com.mrane.data.Marker parent = data.get(room.parentKey);
final String parentKey = parent.getName();
String parentName = parent.getName();
if (!parent.getShortName().equals("0"))
parentName = parent.getShortName();
result.append(" - " + tag + " ");
int start = result.length();
result.append(parentName);
int end = result.length();
result.append(" ");
ClickableSpan parentSpan = new ClickableSpan() {
@Override
public void onClick(View widget) {
editText.setText(parentKey);
displayMap();
}
@Override
public void updateDrawState(TextPaint p) {
p.setColor(Color.rgb(19, 140, 190));
p.setUnderlineText(true);
}
};
result.setSpan(parentSpan, start, end,
SpannableStringBuilder.SPAN_INCLUSIVE_INCLUSIVE);
ClickableSpan restSpan1 = new ClickableSpan() {
private TextPaint ds;
@Override
public void onClick(View widget) {
updateDrawState(ds);
widget.invalidate();
// newCardTouchListener.toggleExpansion();
}
@Override
public void updateDrawState(TextPaint ds) {
ds.bgColor = Color.TRANSPARENT;
ds.setUnderlineText(false);
this.ds = ds;
}
};
ClickableSpan restSpan2 = new ClickableSpan() {
private TextPaint ds;
@Override
public void onClick(View widget) {
updateDrawState(ds);
widget.invalidate();
// newCardTouchListener.toggleExpansion();
}
@Override
public void updateDrawState(TextPaint ds) {
ds.bgColor = Color.TRANSPARENT;
ds.setUnderlineText(false);
this.ds = ds;
}
};
result.setSpan(restSpan1, 0, start,
SpannableStringBuilder.SPAN_EXCLUSIVE_EXCLUSIVE);
result.setSpan(restSpan2, end, end + 1,
SpannableStringBuilder.SPAN_EXCLUSIVE_EXCLUSIVE);
placeSubHeadTextView.setMovementMethod(LinkMovementMethod
.getInstance());
// placeSubHeadTextView.setHighlightColor(Color.TRANSPARENT);
placeSubHeadTextView.setOnClickListener(null);
} else { } else {
buildGoogleApiClient(); placeSubHeadTextView.setOnClickListener(new View.OnClickListener() {
googleMap.setMyLocationEnabled(true);
@Override
public void onClick(View v) {
// newCardTouchListener.toggleExpansion();
}
});
} }
googleMap.getUiSettings().setZoomGesturesEnabled(true); placeSubHeadTextView.setText(result);
}
LatLngBounds iitbBounds = new LatLngBounds(new LatLng(19.1249000, 72.9046000), new LatLng(19.143522, 72.920000));
googleMap.setLatLngBoundsForCameraTarget(iitbBounds);
googleMap.setMaxZoomPreference(30);
googleMap.setMinZoomPreference(14.5f);
// Position the map's camera near Mumbai
LatLng iitb = new LatLng(19.1334, 72.9133);
googleMap.moveCamera(CameraUpdateFactory.newLatLng(iitb));
}
private void checkLocationPermission() {
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(),
Manifest.permission.ACCESS_FINE_LOCATION)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
new AlertDialog.Builder(getActivity())
.setTitle("Location Permission Needed")
.setMessage("This app needs the Location permission, please accept to use location functionality")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
//Prompt the user once explanation has been shown
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
Constants.MY_PERMISSIONS_REQUEST_LOCATION);
}
})
.create()
.show();
private Drawable getLockIcon(com.mrane.data.Marker marker) {
int color = marker.getColor();
int drawableId = R.drawable.lock_all_off;
if (campusMapView.isAddedMarker(marker)) {
if (color == com.mrane.data.Marker.COLOR_BLUE)
drawableId = R.drawable.lock_blue_on;
else if (color == com.mrane.data.Marker.COLOR_YELLOW)
drawableId = R.drawable.lock_on_yellow;
else if (color == com.mrane.data.Marker.COLOR_GREEN)
drawableId = R.drawable.lock_green_on;
else if (color == com.mrane.data.Marker.COLOR_GRAY)
drawableId = R.drawable.lock_gray_on;
}
Drawable lock = getResources().getDrawable(drawableId);
return lock;
}
public void expandCard() {
reCenterMarker();
}
private void reCenterMarker() {
com.mrane.data.Marker marker = campusMapView.getResultMarker();
reCenterMarker(marker);
}
private void reCenterMarker(com.mrane.data.Marker marker) {
PointF p = marker.getPoint();
float shift = getResources().getDimension(R.dimen.expanded_card_height) / 2.0f;
PointF center = new PointF(p.x, p.y + shift);
SubsamplingScaleImageView.AnimationBuilder anim = campusMapView.animateCenter(center);
anim.start();
}
public boolean removeMarker() {
if (campusMapView.getResultMarker() == null) {
return false;
} else {
if (slidingLayout.isPanelExpanded()
|| slidingLayout.isPanelAnchored()) {
slidingLayout.collapsePanel();
} else { } else {
// No explanation needed, we can request the permission. editText.setText("");
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, campusMapView.setResultMarker(null);
Constants.MY_PERMISSIONS_REQUEST_LOCATION); dismissCard();
} }
return true;
} }
} }
protected synchronized void buildGoogleApiClient() { /**
mGoogleApiClient = new GoogleApiClient.Builder(getActivity()) * Hides the card
.addConnectionCallbacks(this) *
.addOnConnectionFailedListener(this) * @return true if the card was visible while this function was called
.addApi(LocationServices.API) */
.build(); public void dismissCard() {
mGoogleApiClient.connect(); cardSlideListener.dismissCard();
campusMapView.invalidate();
} }
@Override public void removeClick(View v) {
public void onLocationChanged(Location location) { this.editText.setText("");
mLastLocation = location; displayMap();
if (mCurrLocationMarker != null) { }
mCurrLocationMarker.remove();
public void indexClick(View v) {
this.putFragment(indexFragment);
this.removeEditTextFocus(null);
this.setCorrectIcons();
}
public void mapClick(View v) {
this.backToMap();
this.removeEditTextFocus("");
}
private void removeEditTextFocus(String text) {
if (this.editTextFocused) {
this.hideKeyboard();
editText.clearFocus();
} }
//Place current location marker if (text == null) {
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
//move map camera
googleMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
googleMap.animateCamera(CameraUpdateFactory.zoomTo(17));
//stop location updates } else if (text.equals("")) {
if (mGoogleApiClient != null) { this.setOldText();
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this); } else {
editText.setText(text);
} }
} }
@Override public FuzzySearchAdapter getAdapter() {
public void onConnectionSuspended(int i) { return adapter;
} }
@Override private void setOldText() {
public void onRequestPermissionsResult(int requestCode, com.mrane.data.Marker oldMarker = campusMapView.getResultMarker();
String permissions[], int[] grantResults) { if (oldMarker == null) {
switch (requestCode) { if (editText.length() > 0) {
case Constants.MY_PERMISSIONS_REQUEST_LOCATION: { editText.getText().clear();
// If request is cancelled, the result arrays are empty. }
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { } else {
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { editText.setText(oldMarker.getName());
if (mGoogleApiClient == null) { }
buildGoogleApiClient(); }
}
googleMap.setMyLocationEnabled(true); private void setCorrectIcons() {
} if (noFragments) {
if (this.handleRemoveIcon()) {
this.noIndexButton();
} else {
this.setVisibleButton(indexIcon);
}
} else {
if (fragment instanceof ListFragment) {
if (this.handleRemoveIcon()) {
this.noIndexButton();
} else {
this.setVisibleButton(indexIcon);
} }
return; } else if (fragment instanceof IndexFragment) {
this.setVisibleButton(mapIcon);
} }
} }
} }
private void noIndexButton() {
indexIcon.setVisibility(View.GONE);
mapIcon.setVisibility(View.GONE);
}
private boolean handleRemoveIcon() {
String text = editText.getText().toString();
if (text.isEmpty() || text.equals(null)) {
removeIcon.setVisibility(View.GONE);
return false;
} else {
removeIcon.setVisibility(View.VISIBLE);
return true;
}
}
private void setVisibleButton(ImageButton icon) {
indexIcon.setVisibility(View.GONE);
mapIcon.setVisibility(View.GONE);
icon.setVisibility(View.VISIBLE);
}
@Override @Override
public void onConnectionFailed(ConnectionResult connectionResult) { public void onFocusChange(View v, boolean focus) {
this.editTextFocused = focus;
if (focus) {
this.putFragment(listFragment);
fragmentContainer.setOnTouchListener(this);
String text = editText.getText().toString()
.toLowerCase(Locale.getDefault());
adapter.filter(text);
} else {
fragmentContainer.setOnTouchListener(null);
}
this.setCorrectIcons();
}
private void hideKeyboard() {
} }
@Override @Override
public void onConnected(Bundle bundle) { public boolean onTouch(View arg0, MotionEvent arg1) {
mLocationRequest = new LocationRequest(); if (adapter.getResultSize() != 0) {
mLocationRequest.setInterval(1000); removeEditTextFocus(null);
mLocationRequest.setFastestInterval(1000); }
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY); return false;
if (ContextCompat.checkSelfPermission(getActivity(), }
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) { public void addMarkerClick(View v) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this); campusMapView.toggleMarker();
setAddMarkerIcon();
}
public void playAnimSound(int sound_index) {
if (sound_index >= 0 && sound_index < soundPoolIds.length) {
if (!settingsManager.isMuted()) {
soundPool.play(soundPoolIds[sound_index], 1.0f, 1.0f, 1, 0, 1f);
}
} }
} }
public void playAnimSoundDelayed(int sound_index, long delay) {
Message msg = mHandler.obtainMessage(MSG_PLAY_SOUND, sound_index, 0);
mHandler.sendMessageDelayed(msg, delay);
}
private void setAddMarkerIcon() {
setAddMarkerIcon(campusMapView.getResultMarker());
}
private void setAddMarkerIcon(com.mrane.data.Marker m) {
addMarkerIcon.setImageDrawable(getLockIcon(m));
}
@Override
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
String selection = (String) expAdapter.getChild(groupPosition,
childPosition);
this.hideKeyboard();
this.removeEditTextFocus(selection);
this.backToMap();
return true;
}
public void setExpAdapter(ExpandableListAdapter expAdapter) {
this.expAdapter = expAdapter;
}
private static final String INSTANCE_CARD_STATE = "instanceCardState";
private static final String INSTANCE_VISIBILITY_INDEX = "instanceVisibilityIndex";
public SlidingUpPanelLayout getSlidingLayout() {
return slidingLayout;
}
} }
package com.mrane.campusmap;
import android.content.Context;
import android.graphics.Typeface;
import android.graphics.drawable.ColorDrawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.mrane.data.Marker;
import java.util.HashMap;
import java.util.List;
import app.insti.R;
import app.insti.fragment.MapFragment;
public class ExpandableListAdapter extends BaseExpandableListAdapter {
private Context _context;
private List<String> _listDataHeader;
private HashMap<String, List<String>> _listDataChild;
public ExpandableListAdapter(Context context, List<String> listDataHeader,
HashMap<String, List<String>> listChildData) {
this._context = context;
this._listDataHeader = listDataHeader;
this._listDataChild = listChildData;
}
@Override
public Object getChild(int groupPosition, int childPosititon) {
return this._listDataChild.get(this._listDataHeader.get(groupPosition))
.get(childPosititon);
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public View getChildView(int groupPosition, final int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
String headerTitle = (String) getGroup(groupPosition);
final String childText = (String) getChild(groupPosition, childPosition);
if (convertView == null) {
LayoutInflater infalInflater = (LayoutInflater) this._context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = infalInflater.inflate(R.layout.map_list_item, null);
}
TextView txtListChild = (TextView) convertView
.findViewById(R.id.lblListItem);
View itemGroupColor = (View) convertView.findViewById(R.id.item_group_color);
int color = Marker.getColor(Marker.getGroupId(headerTitle));
itemGroupColor.setBackgroundColor(color);
Typeface regular = Typeface.createFromAsset(_context.getAssets(), MapFragment.FONT_REGULAR);
txtListChild.setTypeface(regular);
txtListChild.setText(childText);
return convertView;
}
@Override
public int getChildrenCount(int groupPosition) {
return this._listDataChild.get(this._listDataHeader.get(groupPosition))
.size();
}
@Override
public Object getGroup(int groupPosition) {
return this._listDataHeader.get(groupPosition);
}
@Override
public int getGroupCount() {
return this._listDataHeader.size();
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
String headerTitle = (String) getGroup(groupPosition);
if (convertView == null) {
LayoutInflater infalInflater = (LayoutInflater) this._context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = infalInflater.inflate(
R.layout.map_expandable_list_header, null);
}
TextView lblListHeader = (TextView) convertView
.findViewById(R.id.lblListHeader);
Typeface regular = Typeface.createFromAsset(_context.getAssets(), MapFragment.FONT_REGULAR);
lblListHeader.setTypeface(regular);
lblListHeader.setText(headerTitle);
ImageView iconExpand = (ImageView) convertView
.findViewById(R.id.icon_expand);
ImageView groupColor = (ImageView) convertView.findViewById(R.id.group_color);
int color = Marker.getColor(Marker.getGroupId(headerTitle));
groupColor.setImageDrawable(new ColorDrawable(color));
if (isExpanded) {
iconExpand.setImageResource(R.drawable.ic_action_expand);
} else {
iconExpand.setImageResource(R.drawable.ic_action_next_item);
}
return convertView;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
package com.mrane.campusmap;
import android.content.Context;
import android.graphics.Typeface;
import android.text.Html;
import android.text.Spanned;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.mrane.data.Marker;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import app.insti.R;
import app.insti.fragment.MapFragment;
public class FuzzySearchAdapter extends BaseAdapter {
Context mContext;
LayoutInflater inflater;
private List<Marker> resultlist = null;
private ArrayList<Marker> inputlist;
private List<ScoredMarker> map;
private Locale l;
private String searchedText = "";
private SettingsManager settingsManager;
private boolean turnOnResidences;
public FuzzySearchAdapter(Context context, List<Marker> inputlist) {
mContext = context;
l = Locale.getDefault();
this.resultlist = inputlist;
Collections.sort(resultlist, new MarkerNameComparator());
inflater = LayoutInflater.from(mContext);
this.inputlist = new ArrayList<Marker>();
this.inputlist.addAll(resultlist);
map = new ArrayList<ScoredMarker>();
}
public class ViewHolder {
TextView label;
LinearLayout rowContainer;
}
public class ScoredMarker {
Marker m;
int score;
public ScoredMarker(int score, Marker m) {
this.m = m;
this.score = score;
}
}
public int getResultSize() {
return resultlist.size();
}
@Override
public int getCount() {
if (this.getResultSize() == 0) {
return 1;
}
return resultlist.size();
}
@Override
public Marker getItem(int position) {
return resultlist.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View view, ViewGroup parent) {
final ViewHolder holder;
if (view == null) {
holder = new ViewHolder();
view = inflater.inflate(R.layout.map_row_layout, null);
holder.label = (TextView) view.findViewById(R.id.label);
Typeface regular = Typeface.createFromAsset(mContext.getAssets(),
MapFragment.FONT_REGULAR);
holder.label.setTypeface(regular);
holder.rowContainer = (LinearLayout) view
.findViewById(R.id.row_container);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
// Set the results into TextViews
if (this.getResultSize() == 0) {
if (settingsManager.showResidences()) {
holder.label.setText("Sorry, no results found.");
} else {
if (turnOnResidences) {
holder.label
.setText("There are results in residences. Select show residences from settings.");
} else {
holder.label.setText("Sorry, no results found.");
}
}
} else {
holder.label.setText(getSpannedText(resultlist.get(position)
.getName(), searchedText));
}
return view;
}
private Spanned getSpannedText(String name, String searchedText2) {
String smallLetterName = name.toLowerCase(l);
searchedText2 = searchedText2.toLowerCase(l).replaceAll("\\s", "");
if (searchedText2.equals("")) {
return Html.fromHtml(name);
} else {
String htmlName = "";
if (isShortForm(smallLetterName, searchedText2)) {
htmlName = getHighlightedShortform(name, searchedText2);
} else {
int i = 0;
int j = 0;
while (i < searchedText2.length()) {
if (smallLetterName.charAt(j) == searchedText2.charAt(i)) {
htmlName += "<b>" + name.charAt(j) + "</b>";
i++;
j++;
} else {
htmlName += name.charAt(j);
j++;
}
}
if (j < name.length()) {
htmlName += name.substring(j, name.length());
}
}
return Html.fromHtml(htmlName);
}
}
private String getHighlightedShortform(String name, String searchedText2) {
String smallCapsName = name.toLowerCase(l);
String possibleShortform = "";
for (int i = 0; i < searchedText2.length(); i++) {
possibleShortform = "";
for (int j = 0; j < searchedText2.length(); j++) {
if (j <= i) {
possibleShortform += searchedText2.charAt(j);
} else {
possibleShortform += "(.*)" + " " + searchedText2.charAt(j);
}
}
possibleShortform += "(.*)";
if (smallCapsName.matches(possibleShortform)) {
name = makeBold(name, searchedText2.substring(0, i + 1));
i++;
while (i < searchedText2.length()) {
name = makeBold(name, " " + searchedText2.charAt(i));
i++;
}
}
}
return name;
}
private String makeBold(String name, String substring) {
String smallCapsName = name.toLowerCase(l);
int firstIndex = smallCapsName.indexOf(substring);
if (name.charAt(firstIndex) == ' ') {
name = name.substring(0, firstIndex + 1)
+ "<b>"
+ name.substring(firstIndex + 1,
firstIndex + substring.length())
+ "</b>"
+ name.substring(firstIndex + substring.length(),
name.length());
} else {
name = name.substring(0, firstIndex)
+ "<b>"
+ name.substring(firstIndex,
firstIndex + substring.length())
+ "</b>"
+ name.substring(firstIndex + substring.length(),
name.length());
}
return name;
}
public void filter(String charText) {
turnOnResidences = false;
charText = charText.toLowerCase(Locale.getDefault());
searchedText = charText;
resultlist.clear();
map.clear();
if (charText.length() == 0) {
if (settingsManager.showResidences()) {
resultlist.addAll(inputlist);
} else {
for (Marker m : inputlist) {
if (m.getGroupIndex() != Marker.RESIDENCES) {
resultlist.add(m);
}
}
}
} else if (charText.length() > 10) {
for (Marker m : inputlist) {
if (m.getName().toLowerCase(Locale.getDefault())
.contains(charText)) {
if (settingsManager.showResidences()) {
resultlist.add(m);
} else {
if (m.getGroupIndex() != Marker.RESIDENCES) {
resultlist.add(m);
} else {
turnOnResidences = true;
}
}
}
}
} else {
for (Marker m : inputlist) {
int score = checkModifyMarker(m, charText);
if (score != 0) {
if (settingsManager.showResidences()) {
map.add(new ScoredMarker(score, m));
} else {
if (m.getGroupIndex() != Marker.RESIDENCES) {
map.add(new ScoredMarker(score, m));
} else {
turnOnResidences = true;
}
}
}
}
resultlist = sortByScore(map);
}
notifyDataSetChanged();
}
private List<Marker> sortByScore(List<ScoredMarker> tempScore) {
List<Marker> templist = new ArrayList<Marker>();
Collections.sort(tempScore, new MarkerScoreComparator());
for (ScoredMarker k : tempScore) {
templist.add(k.m);
}
return templist;
}
private int checkModifyMarker(Marker m, String charText) {
int tempScore = 5;
String tempCharText = "(.*)";
for (int i = 0; i < charText.length(); i++) {
tempCharText += charText.charAt(i) + "(.*)";
}
if (m.getName().toLowerCase(l).matches(tempCharText)) {
boolean b = false;
if (m.getName().toLowerCase(l).startsWith(charText)) {
return 1;
}
if (isShortForm(m.getName(), charText)) {
return 2;
}
for (String s : m.getName().split(" ")) {
b = b || s.toLowerCase(l).startsWith("" + charText.charAt(0));
if (!b) {
tempScore += 10;
}
if (s.startsWith(charText)) {
return 3;
}
}
if (b) {
return tempScore;
} else {
return 0;
}
} else {
return 0;
}
}
private boolean isShortForm(String name, String charText) {
name = name.toLowerCase(l);
charText = charText.toLowerCase(l).replaceAll("\\s", "");
String possibleShortform = "";
for (int i = 0; i < charText.length(); i++) {
possibleShortform = "";
for (int j = 0; j < charText.length(); j++) {
if (j <= i) {
possibleShortform += charText.charAt(j);
} else {
possibleShortform += "(.*)" + " " + charText.charAt(j);
}
}
possibleShortform += "(.*)";
if (name.matches(possibleShortform)) {
return true;
}
}
return false;
}
public SettingsManager getSettingsManager() {
return settingsManager;
}
public void setSettingsManager(SettingsManager settingsManager) {
this.settingsManager = settingsManager;
}
public class MarkerScoreComparator implements Comparator<ScoredMarker> {
public int compare(ScoredMarker m1, ScoredMarker m2) {
return m1.score - m2.score;
}
}
public class MarkerNameComparator implements Comparator<Marker> {
public int compare(Marker m1, Marker m2) {
return m1.getName().toLowerCase(l)
.compareTo(m2.getName().toLowerCase(l));
}
}
}
package com.mrane.campusmap;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnGroupClickListener;
import android.widget.ExpandableListView.OnGroupCollapseListener;
import android.widget.ExpandableListView.OnGroupExpandListener;
import com.mrane.data.Marker;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import app.insti.R;
import app.insti.fragment.MapFragment;
public class IndexFragment extends Fragment implements OnGroupExpandListener,
OnGroupCollapseListener, OnGroupClickListener {
MapFragment mainActivity;
ExpandableListAdapter adapter;
HashMap<String, Marker> data;
View rootView;
ExpandableListView list;
List<String> headers = new ArrayList<String>();
HashMap<String, List<String>> childData = new HashMap<String, List<String>>();
int pos;
int prevGroup = -1;
public IndexFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mainActivity = MapFragment.getMainActivity();
data = mainActivity.data;
if (headers.isEmpty()) {
setHeaderAndChildData();
}
adapter = new ExpandableListAdapter(mainActivity.getContext(), headers, childData);
rootView = inflater.inflate(R.layout.map_index_fragment, container, false);
list = (ExpandableListView) rootView.findViewById(R.id.index_list);
mainActivity.setExpAdapter(adapter);
list.setAdapter(adapter);
list.setOnChildClickListener(mainActivity);
list.setOnGroupExpandListener(this);
list.setOnGroupCollapseListener(this);
list.setOnGroupClickListener(this);
return rootView;
}
@Override
public void onResume() {
String name = mainActivity.editText.getText().toString();
if(name.isEmpty()) {
collapseAllGroups();
list.setSelectedGroup(0);
} else {
if(data.containsKey(name)) {
String groupName = data.get(name).getGroupName();
int groupId = getGroupId(groupName);
if(groupId != -1) {
list.expandGroup(groupId);
list.setSelectedGroup(groupId);
}
}
}
super.onResume();
}
private int getGroupId(String groupName) {
int groupCount = adapter.getGroupCount();
int temp = -1;
for (int i=0; i < groupCount; i++) {
if(adapter.getGroup(i).equals(groupName)) {
temp = i;
}
}
return temp;
}
private void collapseAllGroups() {
int groupCount = adapter.getGroupCount();
for (int i=0; i < groupCount; i++) {
list.collapseGroup(i);
}
}
private void setChildData() {
Collection<Marker> keys = data.values();
for (Marker key : keys) {
List<String> child = childData.get(key.getGroupName());
child.add(key.getName());
}
sortChildData();
}
private void sortChildData() {
for (String header : headers) {
List<String> child = childData.get(header);
Collections.sort(child);
}
}
private void setHeaderAndChildData() {
String[] headerString = Marker.getGroupNames();
Collections.addAll(headers, headerString);
for (String header : headers) {
childData.put(header, new ArrayList<String>());
}
setChildData();
}
@Override
public void onGroupExpand(int groupPosition) {
if (prevGroup != -1 && prevGroup != groupPosition) {
list.collapseGroup(prevGroup);
}
prevGroup = groupPosition;
}
@Override
public void onGroupCollapse(int groupPosition) {
if (prevGroup != -1) {
//list.setSelectionFromTop(prevGroup, 0);
}
}
@Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition,
long id) {
// Implement this method to scroll to the correct position as this doesn't
// happen automatically if we override onGroupExpand() as above
parent.smoothScrollToPosition(groupPosition);
// Need default behaviour here otherwise group does not get expanded/collapsed
// on click
if (parent.isGroupExpanded(groupPosition)) {
parent.collapseGroup(groupPosition);
} else {
parent.expandGroup(groupPosition);
}
return true;
}
}
package com.mrane.campusmap;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import com.mrane.data.Marker;
import java.util.HashMap;
import app.insti.R;
import app.insti.fragment.MapFragment;
public class ListFragment extends Fragment {
MapFragment mainActivity;
FuzzySearchAdapter adapter;
HashMap<String, Marker> data;
View rootView;
ListView list;
public ListFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mainActivity = MapFragment.getMainActivity();
adapter = mainActivity.getAdapter();
rootView = inflater.inflate(R.layout.map_list_fragment, container, false);
list = (ListView) rootView.findViewById(R.id.suggestion_list);
list.setAdapter(adapter);
list.setOnItemClickListener(mainActivity);
list.setOnTouchListener(mainActivity);
list.setFastScrollEnabled(true);
return rootView;
}
}
package com.mrane.campusmap;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.res.Resources;
import android.preference.PreferenceManager;
import app.insti.R;
public class SettingsManager implements OnSharedPreferenceChangeListener{
private SharedPreferences sharedPrefs;
private String muteKey;
private String residencesKey;
private String lastUpdatedKey;
public SettingsManager(Context context){
sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
sharedPrefs.registerOnSharedPreferenceChangeListener(this);
Resources res = context.getResources();
muteKey = "mute";
residencesKey = "residences";
lastUpdatedKey = "lastupdated";
}
public boolean isMuted(){
return sharedPrefs.getBoolean(muteKey, false);
}
public boolean showResidences(){
return sharedPrefs.getBoolean(residencesKey, true);
}
public long getLastUpdatedOn() {
return sharedPrefs.getLong(lastUpdatedKey, 0);
}
public void setLastUpdatedOn(long lastUpdatedOn) {
sharedPrefs.edit().putLong(lastUpdatedKey, lastUpdatedOn).commit();
}
@Override
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
}
}
package com.mrane.data;
public class Building extends Marker {
public String[] children;
public Building(String name, String shortName, float x, float y,
int groupIndex, String[] children, String description) {
super(name, shortName, x, y, groupIndex, description);
this.children = children;
}
}
package com.mrane.data;
import android.content.Context;
import java.util.HashMap;
public class Locations {
public HashMap<String, Marker> data = new HashMap<String, Marker>();
public Locations(Context context) {
Marker m0 = new Room("Advanced Centre for Research in Electronics",
"ACRE", 4081, 1344, 1, "NanoTech. & Science Research Centre",
"Inside", "");
data.put(m0.getName(), m0);
Marker m1 = new Building(
"Aerospace Engineering Department",
"Aero engg",
4153,
2249,
1,
new String[] { "Centre for Aerospace Systems Design and Engineering" },
"http://www.aero.iitb.ac.in\nPhone No.: +912225767101 / +912225767102\nFax No.: +91222572 2602.\nEmail: office@aero.iitb.ac.in \nThe department offers academic programs for B. Tech, M. Tech, Ph. D. Specialization are offered: Aerodynamics, Control and Guidance, Propulsion, Structures, and Systems Engineering");
data.put(m1.getName(), m1);
Marker m2 = new Marker("B 22 Ananta ", "0", 4709, 865, 3,
"Flat nos. 147-206");
data.put(m2.getName(), m2);
Marker m3 = new Marker("B 23 Aravali ", "0", 4415, 936, 3,
"Flat nos. 207-267");
data.put(m3.getName(), m3);
Marker m4 = new Room("ATM - Canara Bank near Gulmohar", "Canara ATM",
2989, 2154, 6, "Canara Bank", "First floor", "");
data.put(m4.getName(), m4);
Marker m5 = new Marker("ATM - Canara Bank near H6", "Canara ATM", 2543,
842, 6, "");
data.put(m5.getName(), m5);
Marker m6 = new Room("ATM - State Bank near Tansa", "SBI ATM", 3028,
989, 6, "Tansa House King of campus (Proj. Staff Boys)",
"Near", "");
data.put(m6.getName(), m6);
Marker m7 = new Marker("Jayantia B-19", "0", 1413, 2885, 3, "");
data.put(m7.getName(), m7);
Marker m8 = new Room("Badminton Court", "0", 3480, 1081, 8,
"Indoor Stadium", "Inside", "");
data.put(m8.getName(), m8);
Marker m9 = new Room(
"Bio-diesel Lab",
"0",
4220,
1558,
12,
"Treelabs",
"Backside",
"www.che.iitb.ac.in/chea/biosynth/be-a-part.php\ncontact@biosynthiitb.org\nProject ‘Biosynth’ is an initiative by the students of the Department of Chemical Engineering, IIT Bombay to install a Biodiesel plant. This student-managed initiative was started in 2008. The R & D activities at the plant include:\nthe adaptation of the standard biodiesel production process to the available waste vegetable oil, the quality control for the biodiesel produced, allied issues pertaining to design and planning and research projects.");
data.put(m9.getName(), m9);
Marker m10 = new Building(
"Biosciences and Bioengineering Department",
"BSBE ",
3934,
2241,
1,
new String[] { "WRCBB Wadhwani Research Centre in Biosciences and Bioengineering " },
"Phone: +912225767771\nFax: +912225767771\nE-mail: office.bio@iitb.ac.in\nThe department offers academic programs in MSc (Biotechnology), MTech (Biomedical Engineering), MSc-PhD Dual Degree Program, PhD Program ");
data.put(m10.getName(), m10);
Marker m11 = new Marker("Boat House", "0", 1960, 1757, 9,
"Timings: 6 am to 6 pm");
data.put(m11.getName(), m11);
Marker m12 = new Marker("Brewberrys Cafe", "Brewberrys", 2967, 1271, 5,
"Ph no: +912265641001, Hostel 8, IIT Bombay, Powai, Mumbai");
data.put(m12.getName(), m12);
Marker m13 = new Building(
"Campus School",
"0",
3331,
2865,
7,
new String[] { "Kindergarten School" },
"Principal: MS.BHAGWAT A.S\n+912225768992\nCampus School began as a primary school on 29 June 1976. V to X standard was added by 1986 with 100% results in X std in 1986, 1987 and 1988. The junior college classes FYJC or XI Std and SYJC or XII Std were started in science stream under Principal Chandra Rao in 1989. The Primary to JC complex has about 400 students on its roll, 35 teachers and 20 non-teaching staff. Admission to all classes is restricted to children of IIT employees with some seats made available to the children of NITIE and SAMEER employees.");
data.put(m13.getName(), m13);
Marker m14 = new Marker(
"Central Library",
"0",
3820,
1455,
1,
"http://www.library.iitb.ac.in\n+912225768921\nLibrary Working Hours\nMonday through Friday 0900 - 2300 hrs\nMonday through Friday 0900 - 0100 hrs (during examination)\nSaturdays / Sundays / Holidays 1000 - 1700 hrs\nSaturdays / Sundays / Holidays 1000 - 0100 hrs (during examination)\n\nCirculation Hours\nMonday through Friday 0900-2000 hrs\nSaturday, Sunday & Holidays 1100-1300 hrs\nSelf Issue / self Check out, any time till library is open.\nStudy room books issued for overnight, one hour before closing of the library on all days");
data.put(m14.getName(), m14);
Marker m15 = new Marker(
"Centre for Environmental Science and Engineering",
"CESE",
4340,
1985,
1,
"http://www.cese.iitb.ac.in\nTel +912225767851 Fax +912225764650\nThe Centre offers M.Tech. and Ph.D. programmes, which are interdisciplinary in nature and consists of course work followed by a research project. The duration of the Ph.D. programme varies depending upon the background of the candidate.");
data.put(m15.getName(), m15);
Marker m16 = new Room(
"Chemistry Department",
"Chemistry",
3788,
2350,
1,
"Chemical Engineering Department",
"",
"http://www.chem.iitb.ac.in\nPhone: +912225767151 \nFax: +912225723480, +912225767152 \nThe department offers academic programs for M.Sc, Ph.D, (M.Sc + Ph.D) Dual Degree Courses, 4 year BS degree course (From 2014, the 5 year Integrated M.Sc course has been replaced by the 4 year B.S course).");
data.put(m16.getName(), m16);
Marker m17 = new Building(
"Civil Engineering Department",
"Civil",
3879,
1804,
1,
new String[] {
"Centre for Urban Science and Engineering (inside civil)",
"Inter-disciplinary Programme in Climate Studies" },
"http://www.civil.iitb.ac.in\nTel:+912225767301\nFax:+912225767302\nThe department offers academic programs for B Tech, Dual Degree (B Tech + M Tech), M Tech, MS and Ph.D across different divisions such as\nBuilding Technology and Construction Management (BTCM)\nEnvironmental and Water Resources Engineering (EWRE)\nGeotechnical Engineering (GT)\nStructural Engineering (ST)\nTransportation Engineering (TR)");
data.put(m17.getName(), m17);
Marker m18 = new Building("Convocation Hall", "0", 3255, 1711, 4,
new String[] { "Institute Music Room" }, "Tel: +912225762781");
data.put(m18.getName(), m18);
Marker m19 = new Building(
"NanoTech. & Science Research Centre",
"CRNTS",
4081,
1344,
1,
new String[] { "Advanced Centre for Research in Electronics",
"Sophisticated Analytical Instruments Facility" },
"http://www.iitb.ac.in/~crnts\nTel:+912225767691\nCRNTS offers programs such as\nDual degree programme-1 (B.Tech. Engg. Physics & M.Tech. Engg. Physics with specialization in Nanoscience. Admission Through: JEE. Offered by: Department of Physics. Duration: 5 years)\n\nDual degree programme-2 (M.Sc. Physics & M.Tech. in Materials Science with specialization in Nanoscience., Input : B.Sc. (Physics), Admission through: J.A.M. Jointly offered by Department of Physics & Department of Metallurgical Engg. & Materials Science)\n\nPh.D ( Interdisciplinary program. Research Domains include Nanomaterials, Nanobiotechnology, Nanofluidics, Nanoelectronics, Nanomanufacturing, Nanosensors, Computational research in Nanosystems)");
data.put(m19.getName(), m19);
Marker m20 = new Marker(
"Centre of Studies in Resources Engineering",
"CSRE",
4096,
1993,
1,
"http://www.csre.iitb.ac.in\nTel:+912225767662\nThe centre offers Ph.D, M Tech, UG Minor and institute elective. Research areas include Spatial Analysis, Digital Image Processing, Global Positioning System (GPS) and Photogrammetry, Geocomputational Systems, Microwave Remote Sensing, Snow and Glacier Studies, Geology and Mineral Resources, Agro-Informatics and rural development, Terrain evaluation group, Environment, natural hazards and disaster management, Coastal and marine sciences");
data.put(m20.getName(), m20);
Marker m21 = new Marker("A1 Director Bungalow", "Dir. Bunglw.", 2594,
2495, 3, "");
data.put(m21.getName(), m21);
Marker m22 = new Marker("Defence Research & Development Organization",
"DRDO", 4125, 1048, 3, "Flat nos. 101 - 404");
data.put(m22.getName(), m22);
Marker m23 = new Marker(
"Earth Science Department",
"Earth Sci",
4038,
2123,
1,
"http://www.geos.iitb.ac.in\n+912225767251,+912225767265\nThe department offers academic programs for M.Sc (Applied Geology, Applied Geophysics, Geoexploration), M Tech (Petroleum Geoscience) and Ph.D. Research areas include Mineralogy, Geochemistry and Ore Deposits Structural Geology Igneous and Metamorphic Petrology Engineering geology, Hydro-geology Sedimentology Stratigraphy and Micro-Paleontology Mathematical Geology/ Ore Deposit Modelling Rock Magnetism and Marine Geology Seismology, Geothermics");
data.put(m23.getName(), m23);
Marker m24 = new Building(
"Electrical Engineering Annexe Building",
"Elec engg Anx",
3932,
1997,
1,
new String[] { "Centre for Technology Alternatives for Rural Areas" },
"http://www.ee.iitb.ac.in\n+912225764408 \n\n");
data.put(m24.getName(), m24);
Marker m25 = new Building(
"Electrical Engineering Department",
"Elec engg",
3780,
1900,
1,
new String[] { "Computer Centre" },
"http://www.ee.iitb.ac.in\nMain office is inside GG Building on second floor\nContact persons\nMadhumati Shetty +912225767401\nVaishali Deshpande +912225767402\nSantosh S. Kharat +912225767402\nTanvi D. Shelatkar +912225767402\nB Tech, B Tech Honors, Dual Degree Program (B Tech + M Tech), M Tech (Full time 2 yrs, Part time 3yrs with specializations such as Communications, Engineering (termed as EE1), Control and Computing (EE2), Power Electronics and Power System (EE3), Microelectronics and VLSI (EE4), Electronic Systems (EE5)) and Ph D");
data.put(m25.getName(), m25);
Marker m26 = new Building(
"Chemical Engineering Department",
"Chem Engg",
3788,
2350,
1,
new String[] { "Chemistry Department" },
"http://www.che.iitb.ac.in\n+912225767201, +912225767202\nPrograms offered in B Tech, M Tech, Dual Degree (M Tech + Ph D) and Ph D. Research areas include Biological Systems Engineering, Energy & Environment, Materials Engineering, Process Systems Engineering, Reactor Engineering, and Transport Phenomena and Complex Fluids");
data.put(m26.getName(), m26);
Marker m27 = new Marker("Electrical Maintenence", "Elec Maint", 4544,
1830, 1, "Tel: +912225767971/ +912225764077");
data.put(m27.getName(), m27);
Marker m28 = new Marker("Guest House/ Jalvihar", "Jalvihar", 2610,
2138, 3, "Tel: +912225768940 / +912225768942 / +912225768943");
data.put(m28.getName(), m28);
Marker m29 = new Marker("Guest House/ Vanvihar", "Vanvihar", 2881,
2106, 3, "Tel: +912225761200 / +912225768945");
data.put(m29.getName(), m29);
Marker m30 = new Room("Gulmohar Restaurant", "Gulmohar", 2989, 2154, 5,
"Canara Bank", "Second floor",
"Tel: +912225762783 / Tel: +912225762786");
data.put(m30.getName(), m30);
Marker m31 = new Marker("Hospital", "Hosp.", 3018, 1917, 9,
"Hospital Tel: +912225767051,\nAmbulance Tel: +912225761101");
data.put(m31.getName(), m31);
Marker m32 = new Marker(
"Hostel 01 Queen of the campus",
"H1",
3908,
1077,
2,
"Hostel security: +912225762601\nHall Manager: +912225762701\nG. Sec: Ratikant +919930836852");
data.put(m32.getName(), m32);
Marker m33 = new Marker(
"Hostel 10 Annexe (Girls Hostel)",
"H10 Annx",
2886,
2452,
2,
"Hostel security: +912225762610\nHall Manager: +912225762710\nG. Sec: Madhu Lekha +919769372532");
data.put(m33.getName(), m33);
Marker m34 = new Marker(
"Hostel 10 New (Girls Hostel)",
"H10 New",
3005,
2342,
2,
"Hostel security: +912225762610\nHall Manager: +912225762710\nG. Sec: Madhu Lekha +919769372532");
data.put(m34.getName(), m34);
Marker m35 = new Marker(
"Hostel 10A QIP building (Girls Hostel)",
"H10A QIP",
4716,
1448,
2,
"Hostel security: +912225762619\nHall Manager: +912225762719\nG. Sec: Sagarika Kumar +919167273231");
data.put(m35.getName(), m35);
Marker m36 = new Building(
"Hostel 11 Athena (Girls Hostel)",
"H11",
2987,
1368,
2,
new String[] { "Printing and photocopying H11" },
"Hostel security: +912225762611\nHall Manager: +912225762711\nG. Sec: Nanditha +919769834234");
data.put(m36.getName(), m36);
Marker m37 = new Marker(
"Hostel 12 Crown of the campus",
"H12",
2096,
667,
2,
"Hostel security: +912225762612\nHall Manager: +912225762712\nG. Sec: Ashutosh +919167782489");
data.put(m37.getName(), m37);
Marker m38 = new Building(
"Hostel 13 House of Titans",
"H13",
1918,
745,
2,
new String[] { "H13 Night Canteen" },
"Hostel security: +912225762613\nHall Manager: +912225762713\nG. Sec: Raj Kumar Yadav +919769484219");
data.put(m38.getName(), m38);
Marker m39 = new Building(
"Hostel 14 Silicon ship",
"H14",
2114,
800,
2,
new String[] { "Amul Parlour" },
"Hostel security: +912225762614\nHall Manager: 022-25762714\nG. Sec: Mayuresh Pant +919730694513");
data.put(m39.getName(), m39);
Marker m40 = new Marker("Hostel 15", "H15", 4196, 870, 2,
"Hostel security: +912225762715\nHall Manager: \nG. Sec:");
data.put(m40.getName(), m40);
Marker m41 = new Marker("Hostel 16", "H16", 3972, 849, 2,
"Hostel security: +91222576 2716\nHall Manager: 022-2576\nG. Sec:");
data.put(m41.getName(), m41);
Marker m42 = new Marker(
"Hostel 02 The wild ones",
"H2",
3672,
1000,
2,
"Hostel security:+912225762602\nHall Manager: +912225762702\nG. Sec: Manohar Reddy Devarpalli +918796879949");
data.put(m42.getName(), m42);
Marker m43 = new Marker(
"Hostel 03 Vitruvians",
"H3 ",
3435,
946,
2,
"Hostel security: +912225762603\nHall Manager: +912225762703\nG. Sec: Arvind Jangid +919820525369");
data.put(m43.getName(), m43);
Marker m44 = new Marker(
"Hostel 04 Madhouse",
"H4",
3176,
867,
2,
"Hostel security: +912225762604\nHall Manager: +912225762704\nG. Sec: Kumar Gaurav +919969800320");
data.put(m44.getName(), m44);
Marker m45 = new Marker(
"Hostel 05 Penthouse",
"H5",
2820,
970,
2,
"Hostel security: +912225762605\nHall Manager: +912225762705\nG. Sec: Shashank Patidar +919820717487");
data.put(m45.getName(), m45);
Marker m46 = new Marker(
"Hostel 06 Vikings",
"H6",
2500,
748,
2,
"Hostel security: +912225762606\nHall Manager:+912225762706\nG. Sec: Anil Reddy +919022623186");
data.put(m46.getName(), m46);
Marker m47 = new Marker(
"Hostel 07 The lady of the lake",
"H7",
2454,
942,
2,
"Hostel security: +912225762607\nHall Manager: +912225762707\nG. Sec: Archit Laddha +919930239739");
data.put(m47.getName(), m47);
Marker m48 = new Building(
"Hostel 08 Woodland",
"H8",
2834,
1257,
2,
new String[] { "Printing and photocopying H8" },
"Hostel security: +912225762608\nHall Manager:+912225762708\nG. Sec: Mayur Kalambe +919920147585");
data.put(m48.getName(), m48);
Marker m49 = new Marker(
"Hostel 09 Nawaabon Ki Basti",
"H9",
2676,
844,
2,
"Hostel security: +912225762609\nHall Manager: +912225762709\nG. Sec: Shubham Meena +919619835583");
data.put(m49.getName(), m49);
Marker m50 = new Building(
"Humanities and Social Sciences Department",
"HSS",
3911,
2171,
1,
new String[] { "Aerospace Engineering Annexe" },
"http://www.hss.iitb.ac.in\n+912225767351 / +91222576 7351 / +912225767352\nThe department offers academic programs for B. Tech, M. Phil, Ph. D. Research areas include Economics, English, Philosophy, Psychology, Sociology");
data.put(m50.getName(), m50);
Marker m51 = new Building(
"Industrial Design Centre",
"IDC",
4207,
1732,
1,
new String[] { "IDC Canteen", "IDC Shakti" },
"http://www.idc.iitb.ac.in\n+91222576 7801\nThe department offers academic programs for M. Des and Ph. D. Sub-disciplines include Product Design, Industrial Design, Visual Communication, Animation, Interaction Design, Mobility and vehicle design");
data.put(m51.getName(), m51);
Marker m52 = new Building("Indoor Stadium", "0", 3480, 1081, 8,
new String[] { "Badminton Court" }, "");
data.put(m52.getName(), m52);
Marker m53 = new Room(
"Industrial Research & Consultancy Centre",
"IRCC",
3505,
1867,
1,
"School of Management",
"Level 2",
"Tel: +912225767030, +912225767039\nwww.ircc.iitb.ac.in\nThe Industrial Research and Consultancy Centre (IRCC) co-ordinates and facilitates all research and development activities at the Institute.");
data.put(m53.getName(), m53);
Marker m54 = new Building(
"Kanwal Rekhi School of Information Technology ",
"KReSIT",
3301,
2106,
1,
new String[] { "KReSIT Canteen", "Faqir Chand Kohli Auditorium" },
"For admission / general queries +9125767967 / +9125767977\nOffice +9125767901 / +9125767902\nSecurity +912225762784");
data.put(m54.getName(), m54);
Marker m55 = new Marker("Kshitij Udyan", "0", 2971, 1744, 9, "");
data.put(m55.getName(), m55);
Marker m56 = new Marker("Kendriya Vidyalaya ", "KV", 3883, 2714, 7,
"Tel: +912225768983");
data.put(m56.getName(), m56);
Marker m57 = new Marker("Lake Side Gate no. 1", "Lakeside Gate", 792,
2777, 10, "Tel: +912225761124");
data.put(m57.getName(), m57);
Marker m58 = new Building("Lecture Hall Complex - 1 & 2",
"Lec Hall 1 & 2", 3570, 2152, 4, new String[] {
"LT 001 (LCT 01)", "LT 002 (LCT 02)",
"LT 003 (LCT 03)", "LT 004 (LCT 04)",
"LT 005 (LCT 05)", "LT 006 (LCT 06)",
"LT 101 (LCT 11)", "LT 102 (LCT 12)",
"LT 103 (LCT 13)", "LT 104 (LCT 14)",
"LT 105 (LCT 15)", "LT 106 (LCT 16)",
"LT 201 (LCT 21)", "LT 202 (LCT 22)",
"LT 203 (LCT 23)", "LT 204 (LCT 24)",
"LT 205 (LCT 25)", "LT 206 (LCT 26)",
"LT 301 (LCT 31)", "LT 302 (LCT 32)",
"LT 303 (LCT 33)", "LT 304 (LCT 34)",
"LT 305 (LCT 35)", "LT 306 (LCT 36)", "LC 001 (LCC 1)",
"LC 002 (LCC 2)", "LC 101 (LCC 11)", "LC 102 (LCC 12)",
"LC 201 (LCC 21)", "LC 202 (LCC 22)",
"LC 301 (LCC 31)", "LC 302 (LCC 32)",
"LH 101 (LCH 11)", "LH 102 (LCH 12)",
"LH 301 (LCH 31)", "LH 302 (LCH 32)" }, "");
data.put(m58.getName(), m58);
Marker m59 = new Building("Lecture Hall Complex - 3", "Lec Hall 3",
3779, 2220, 4,
new String[] { "HALL 1 (LA 101)", "HALL 2 (LA 102)",
"HALL 3 (LA 103)", "HALL 4 (LA 104)" }, "");
data.put(m59.getName(), m59);
Marker m60 = new Building("Main Building", "0", 3628, 1640, 1,
new String[] { "Hostel Coordinating Unit",
"Graduate apptitude test in engineering Office",
"Joint Admission Test for M.Sc. Office",
"Joint Entrance Examination Office",
"Printing and photocopying Main Building" }, "");
data.put(m60.getName(), m60);
Marker m61 = new Marker("Main Gate no. 2", "Main Gate", 2259, 3237, 10,
"Tel: +9125768978 / +9125761123. Tum Tum coupons available at Main Gate");
data.put(m61.getName(), m61);
Marker m62 = new Marker("Market Gate, Y point Gate no. 3",
"Market Gate", 3829, 2972, 10,
"Tel: +912225768979 / +912225761121");
data.put(m62.getName(), m62);
Marker m63 = new Building(
"Mathematics Department",
"Maths",
3928,
1496,
1,
new String[] {
"Centre for Formal Design and Verification of Software",
"Centre for Distance Engineering Education Programme",
"Old Software Lab",
"Inter-disciplinary Programme in Educational Technology" },
"http://www.math.iitb.ac.in\nTel: +912225767451\nB Tech (core courses), MSc (ASI, Maths), Ph D");
data.put(m63.getName(), m63);
Marker m64 = new Building(
"Mechanical Engineering Department",
"Mech ",
4009,
1645,
1,
new String[] { "Industrial Engineering and Operations Research" },
"http://www.me.iitb.ac.in\nTel: +912225762545 Ext. 7500, 7501, 2576 7500, 2576 7501.\nThe department offers academic programs for B. Tech, Dual degree, M. Tech and Ph. D. Research areas include design enggineering, manufacturing enggineering, thermal and fluid enggineering");
data.put(m64.getName(), m64);
Marker m65 = new Marker("Medical Store", "Med. Store", 4000, 2808, 9,
"");
data.put(m65.getName(), m65);
Marker m66 = new Building(
"Metallurgical Engineering and Material Science Department",
"MEMS",
3631,
2044,
1,
new String[] {
"Inter-disciplinary Programme in Corrosion Science & Engineering",
"Aqueous corrosion lab", "Corrosion lab I",
"Corrosion science paint lab" },
"http://www.met.iitb.ac.in\nTel: +912225767601 / +912225767602\nThe department offers academic programs for B. Tech, Dual degree (B Tech + M Tech), M. Tech and Ph. D. Dual degree specializations include Ceramics and Composites and Metallurgical Process Engineering. M Tech specializations include Materials Science, Steel Technology, Process Engineering and Corrosion Science.");
data.put(m66.getName(), m66);
Marker m67 = new Building("Non- Academic Staff Association", "NASA",
4326, 1896, 1, new String[] { "Printing Press" },
"Tel: +912225768919");
data.put(m67.getName(), m67);
Marker m68 = new Marker("NCC Office", "0", 3387, 1421, 9,
"Tel: +912225768917");
data.put(m68.getName(), m68);
Marker m69 = new Marker("Nestle Cafe (Coffee Shack)", "Coffee Shack",
3492, 1784, 5, "");
data.put(m69.getName(), m69);
Marker m70 = new Marker(
"New Computer Science Engineering Department",
"New CSE",
3422,
1986,
1,
"http://www.cse.iitb.ac.in\nTel: +912225767901/02\nThe department offers academic programs for B. Tech, Dual degree (B Tech + M Tech), M Tech, Dual Degree PG (M. Tech + Ph. D) and Ph. D. Research areas include algorithms, programming languages and Compilers, database and information systems, artificial intelligence and natural language processing, software engineering, formal methods, distributed systems, computer networks, data mining, computer graphics, computer vision and image understanding, real-time and embedded systems, formal languages and bio-inspired computing");
data.put(m70.getName(), m70);
Marker m71 = new Marker("B 24 Nilgiri", "B 24 Nilgiri", 3318, 2324, 3,
"Flat nos. 268-326 ");
data.put(m71.getName(), m71);
Marker m72 = new Building(
"Old Computer Science Engineering Department",
"Old CSE",
4002,
1545,
1,
new String[] { "New Software Lab" },
"http://www.cse.iitb.ac.in\nTel: +912225767701 / +912225767702 / +912225762771\nThe department offers academic programs for B. Tech, Dual degree (B Tech + M Tech), Dual Degree PG (M. Tech + Ph. D) and Ph. D. Research areas include algorithms, programming languages and Compilers, database and information systems, artificial intelligence and natural language processing, software engineering, formal methods, distributed systems, computer networks, data mining, computer graphics, computer vision and image understanding, real-time and embedded systems, formal languages and bio-inspired computing");
data.put(m72.getName(), m72);
Marker m73 = new Marker("B 19 Old Multistoried Building- Residence ",
"B 19", 1413, 2885, 3,
"Building lift phone Tel: +912225762884\nFlat nos. 75-98");
data.put(m73.getName(), m73);
Marker m74 = new Marker(
"ONGC Research Centre",
"0",
4234,
2162,
1,
"Currently, the centre is working on a project titled Physical and Numerical Models for Un-conventional Flood Patterns. The project relates to increasing countrys currrent oil production by means of Enhanced Oil Recovery (EOR) processes. ");
data.put(m74.getName(), m74);
Marker m75 = new Marker(
"OrthoCad Lab",
"0",
4644,
1767,
12,
"The OrthoCAD Network Research Cell was established in 2007 to jump-start indigenous research and development activities in orthopaedic reconstruction systems. The OrthoCAD Network addresses a critical need for mega-prostheses to reconstruct massive gaps or loss of bone from osteo-sarcoma (cancer), congenital (birth) defects or trauma (accidents).");
data.put(m75.getName(), m75);
Marker m76 = new Marker(
"Padmavati Devi Temple",
"0",
946,
2178,
9,
"The word Powai is thought to have possibly been derived from the word Poumw, a corrupted form of Pouma which means Padma in Sanskrit. This is due to the fact that the Padmavati Devi Temple, dedicated to Goddess Padmavati and situated on the bank of the Powai lake inside IIT Bombay, dates back to the 10th century AD as per the Archeological Survey of India.\nhttp://www.iitbdevitemple.org");
data.put(m76.getName(), m76);
Marker m77 = new Marker("PC Saxena Auditorium / Leacture Theatre",
"PCSA, LT", 3648, 1790, 4, "022 2576 4999");
data.put(m77.getName(), m77);
Marker m78 = new Marker(
"Physics Department",
"Physics",
3479,
2247,
1,
"The department offers academic programs for B.Tech Engineering Physics (through JEE), Dual degree B.Tech + M.Tech in Engineering Physics with specialisation in Nanoscience (through JEE), MSc Physics 2 Years programme (through JAM), Dual degree programme of MSc and PhD in physics (through JAM). Research areas include Condensed Matter Physics, Photonics and Optics, Nuclear Physics, High Energy Physics, Statistical Physics");
data.put(m78.getName(), m78);
Marker m79 = new Marker("Post Office", "0", 3918, 2846, 9,
"Tel: +912225762774");
data.put(m79.getName(), m79);
Marker m80 = new Marker("Power House", "0", 4671, 1590, 9, "");
data.put(m80.getName(), m80);
Marker m81 = new Room("Printing Press", "Press", 4326, 1896, 9,
"Non- Academic Staff Association", "Inside",
"Tel: +912225768961");
data.put(m81.getName(), m81);
Marker m82 = new Building("Students Activity Centre", "SAC", 3599,
1225, 8, new String[] { "Open Air Theatre" },
"Tel: +912225768968");
data.put(m82.getName(), m82);
Marker m83 = new Room("Sophisticated Analytical Instruments Facility",
"SAIF", 4081, 1344, 1, "NanoTech. & Science Research Centre",
"Inside", "Tel: +912225767691 / +912225767692");
data.put(m83.getName(), m83);
Marker m84 = new Marker("Seminar Hall", "0", 3792, 2025, 4,
"Tel: +912225764912, for booking +912225764420");
data.put(m84.getName(), m84);
Marker m85 = new Marker("Shishu Vihar", "0", 2318, 2851, 9,
"Shishu Vihar is temporarily located at A5\nTel: +912225764978");
data.put(m85.getName(), m85);
Marker m86 = new Marker("Shivalik C 23 (187-240)", "Shivalik C 23",
3129, 2612, 3, "C- Type Quartera Flat nos. 187 - 240");
data.put(m86.getName(), m86);
Marker m87 = new Building(
"School of Management",
"SOM",
3505,
1867,
1,
new String[] { "Industrial Research & Consultancy Centre" },
"http://www.som.iitb.ac.in\nOffice - +912225767781\nPh. D. admissions - +912225767782\nM. Mgt. admissions - +912225768781 \nThe department offers academic programs in Master Of Management Programme - Full Time, Doctoral Programme in Management - PhD Degree, Management Development Programme - For Corporate Executives");
data.put(m87.getName(), m87);
Marker m88 = new Marker("Staff Canteen", "Staff Cant.", 3622, 1547, 5,
"Tel: +912225768952");
data.put(m88.getName(), m88);
Marker m89 = new Marker("Staff Club", "0", 2931, 2027, 8,
"Tel: +912235764075");
data.put(m89.getName(), m89);
Marker m90 = new Marker("Staff Hostel", "0", 2872, 1472, 3,
"Tel: +912225761113");
data.put(m90.getName(), m90);
Marker m91 = new Marker("State Bank of India, IIT Powai branch", "SBI",
2164, 3227, 6,
"Phone +912225722894 / +912225721103\nwork hours: 10:30 am to 4:30 pm");
data.put(m91.getName(), m91);
Marker m92 = new Marker("Swimming Pool (new)", "S. Pool new", 3558,
1141, 8, "Tel: +912225762755");
data.put(m92.getName(), m92);
Marker m93 = new Marker("Swimming Pool (old)", "S. Pool old", 3742,
1229, 8, "Tel: +912225768967");
data.put(m93.getName(), m93);
Marker m94 = new Building(
"Tansa House King of campus (Proj. Staff Boys)", "Tansa", 3028,
932, 2, new String[] { "ATM - State Bank near Tansa" },
"Tel: +912225762620");
data.put(m94.getName(), m94);
Marker m95 = new Marker("Tennis Court (new)", "0", 3046, 1513, 8, "");
data.put(m95.getName(), m95);
Marker m96 = new Marker("Tennis Court (old)", "0", 3177, 1624, 8, "");
data.put(m96.getName(), m96);
Marker m97 = new Marker("Victor Menezes Convention Centre", "VMCC",
4110, 1847, 4, "Tel: +912225761125");
data.put(m97.getName(), m97);
Marker m98 = new Marker("Vidya Niwas", "0", 4911, 1111, 3, "");
data.put(m98.getName(), m98);
Marker m99 = new Marker("Vihar House", "0", 4558, 1429, 3, "");
data.put(m99.getName(), m99);
Marker m100 = new Marker(
"White House",
"0",
1909,
2799,
3,
"B- 20, A wing Tel: +912225762885, Flat nos. 99-110\nB- 20, B wing Tel: +912225762840, Flat nos.111-122");
data.put(m100.getName(), m100);
Marker m101 = new Building("Canara Bank", "0", 2989, 2154, 6,
new String[] { "ATM - Canara Bank near Gulmohar",
"Gulmohar Restaurant" }, "Tel: +912225762797");
data.put(m101.getName(), m101);
Marker m102 = new Room("Hostel Coordinating Unit", "HCU", 3628, 1640,
1, "Main Building", "Inside",
"Chairman Tel: +91222576 8901,\nOfficeTel: +91222576 8900");
data.put(m102.getName(), m102);
Marker m103 = new Room("Graduate apptitude test in engineering Office",
"GATE Off.", 3628, 1640, 1, "Main Building", "Inside",
"Tel: +91222576 2924");
data.put(m103.getName(), m103);
Marker m104 = new Room("Joint Admission Test for M.Sc. Office",
"JAM Off.", 3628, 1640, 1, "Main Building", "Inside",
"Tel: +91222576 2924");
data.put(m104.getName(), m104);
Marker m105 = new Room("Joint Entrance Examination Office", "JEE Off.",
3628, 1640, 1, "Main Building", "Inside", "Tel: +91222576 4063");
data.put(m105.getName(), m105);
Marker m106 = new Marker(
"Energy Science and enggineering",
"ESE",
4239,
2028,
1,
"http://www.ese.iitb.ac.in\nTel: +912225767890\nThe department offers academic programs in Dual degree (B Tech + M Tech), M Tech, M.Sc.-Ph.D and Ph.D. Research areas include Energy Efficiency and Conservation, Solar PV and Thermal, Battery and Storage Engineering, Hydrogen and Fuel Cells, Smart microgrids, Biomass and Bio-Fuels, Wind Energy, Nuclear");
data.put(m106.getName(), m106);
Marker m107 = new Room(
"Centre for Urban Science and Engineering (inside civil)",
"C-USE",
3879,
1804,
1,
"Civil Engineering Department",
"Inside",
"http://cuse.iitb.ac.in\nTel: +912225769301\nPh. D program. Research areas include Planning and Design (Housing, Land use policies, Public Spaces, Risk Management)\nPolicy and Governance (Housing Economics, Health, Education, Employment, Environment) Infrastructure (Buildings,Transportation & Land use, Urban water, Waste Management, Smart Energy); Informatics (Citizen Science, Cyber-Physical Systems, Urban Knowledge, Geo-Spatial Technologies)");
data.put(m107.getName(), m107);
Marker m108 = new Room(
"Centre for Formal Design and Verification of Software",
"CFDVS", 3928, 1496, 1, "Mathematics Department",
"In basement", "http://www.cfdvs.iitb.ac.in\n+912225768701");
data.put(m108.getName(), m108);
Marker m109 = new Room(
"Centre for Technology Alternatives for Rural Areas",
"CTARA",
3932,
1997,
1,
"Electrical Engineering Annexe Building",
"Inside",
"http://www.ctara.iitb.ac.in\nTel: +912225767870\nOffers M. Tech, Ph D and TDSL (Minor for UG). Research areas include agriculture and food, appropriate technology, drinking water, environment, energy and health");
data.put(m109.getName(), m109);
Marker m110 = new Room(
"Centre for Distance Engineering Education Programme", "CDEEP",
3928, 1496, 1, "Mathematics Department", "Ground floor",
"http://www.cdeep.iitb.ac.in\nTel: +912225764820/4812");
data.put(m110.getName(), m110);
Marker m111 = new Room("Computer Centre", "CC", 3932, 1997, 1,
"Electrical Engineering Department", "In room 243",
"http://www.cc.iitb.ac.in\nTel: +912225767751");
data.put(m111.getName(), m111);
Marker m112 = new Room(
"Centre for Aerospace Systems Design and Engineering", "CASDE",
4153, 2249, 1, "Aerospace Engineering Department", "Inside",
"http://www.casde.iitb.ac.in/aboutus\nTel: +912225767840");
data.put(m112.getName(), m112);
Marker m113 = new Room("Centrifugal Lab", "0", 4370, 1395, 12,
"National Geotechnical Centrifuge Facility", "Near", "");
data.put(m113.getName(), m113);
Marker m114 = new Room(
"Concrete Technology Lab",
"Concrete Tech Lab",
4330,
1495,
12,
"Heavy Structure Lab",
"Near",
"Comes under Structural Engineering Laboratories of Civil Engineering Department ");
data.put(m114.getName(), m114);
Marker m115 = new Marker("Cummins Engine Research facility", "Cummins",
4350, 1580, 1,
"Incharge: Prof. Anuradda Ganesh\nTel: +912225764506\nLocation");
data.put(m115.getName(), m115);
Marker m116 = new Room(
"ENELEK Power Sine",
"ENELEK",
4160,
1620,
9,
"Treelabs",
"Beside",
"Enelek is a technology driven company, dedicated to delivery to quality and affordability through state-of-the art solar thermal & solar power products, systems and providing technology solutions & services.\nAddress: CM-06, SINE Office\n3rd Floor, CSRE Building\nIIT Bombay\nPowai, Mumbai - 400076\nContact No. - +919167939941 | info@enelek.com\nCareers Enquiry - career@enelek.com");
data.put(m116.getName(), m116);
Marker m117 = new Room(
"Energy Systems Lab",
"Enrgy Sys Lab",
4230,
1435,
12,
"Geotechnical Engg. Lab",
"Near",
"Comes under Energy Systems Engineering Department\nhttp://www.ese.iitb.ac.in\n+912225767890\nThe department offers academic programs in Dual degree (B Tech + M Tech), M Tech, M.Sc.-Ph.D and Ph.D. Research areas include Energy Efficiency and Conservation, Solar PV and Thermal, Battery and Storage Engineering, Hydrogen and Fuel Cells, Smart microgrids, Biomass and Bio-Fuels, Wind Energy, Nuclear");
data.put(m117.getName(), m117);
Marker m118 = new Building(
"Fluid Mechanics and Fluid Power Lab",
"Fluid Mech Lab",
4060,
1585,
12,
new String[] { "Hydraulics Lab (New)" },
"Comes under Mechanical Engineering Department\nFluid Mechanics Lab Tel: +912225764232 \nFluid Power LabTel: +912225764532 / +912225764549");
data.put(m118.getName(), m118);
Marker m119 = new Room(
"Fuel Cell Research Facility",
"Fuel Cell Re. Fac.",
4525,
1680,
1,
"N1 Bay",
"Inside",
"Comes under Energy Systems Engineering Department\nhttp://www.ese.iitb.ac.in\n+912225764897");
data.put(m119.getName(), m119);
Marker m120 = new Building("Geotechnical Engg. Lab", "GeoTech Lab",
4280, 1425, 12, new String[] { "Energy Systems Lab" },
"Comes under Civil Engineering Department\n+912225764320");
data.put(m120.getName(), m120);
Marker m121 = new Marker(
"GMFL Lab / Geophysical and multiphase Flows Lab", "GMFL Lab",
4530, 1485, 12, "");
data.put(m121.getName(), m121);
Marker m122 = new Room("Greenhouse Lab", "0", 4790, 1055, 12,
"K-Yantra Lab (CSE Dept.)", "Inside", "");
data.put(m122.getName(), m122);
Marker m123 = new Marker("Heat Pump Lab", "0", 4153, 1539, 12,
"Comes under Mechanical Engineering Department\n+912225764527 / +912225764593");
data.put(m123.getName(), m123);
Marker m124 = new Building("Heat Transfer and Thermodynamic Lab",
"Heat Trans Lab", 4390, 1550, 12,
new String[] { "Steam Power Lab" },
"Comes under Mechanical Engineering Department\n+912225764533");
data.put(m124.getName(), m124);
Marker m125 = new Room(
"Heavy Structure Lab",
"0",
4330,
1495,
12,
"Hydraulics Lab",
"Near",
"Comes under Structural Engineering Laboratories of Civil Engineering Department +912225764323");
data.put(m125.getName(), m125);
Marker m126 = new Room(
"Hydraulics Lab",
"0",
4215,
1490,
12,
"Hydraulics Lab",
"Near",
"Comes under Civil Engineering Department\nWater Resources Hydraulics Lab +912225764303");
data.put(m126.getName(), m126);
Marker m127 = new Room("Hydraulics Lab (New)", "0", 4110, 1525, 12,
"Fluid Mechanics and Fluid Power Lab", "Inside",
"Comes under Civil Engineering Department\nHYDRAULICS LAB (VMCC) +912225764301");
data.put(m127.getName(), m127);
Marker m128 = new Room("Hydraulics Lab Workshop", "0", 4180, 1450, 12,
"Hydraulics Lab", "Near", "");
data.put(m128.getName(), m128);
Marker m129 = new Room("IC Engine and Combustion Lab",
"Combustion Lab", 4295, 1570, 12, "Treelabs", "Backside",
"Comes under Mechanical Engineering Department\n+912225764586");
data.put(m129.getName(), m129);
Marker m130 = new Building(
"K-Yantra Lab (CSE Dept.)",
"K-Yantra",
4790,
1055,
1,
new String[] { "Greenhouse Lab" },
"ERTS Lab\nFirst Floor, KReSIT Building, CSE Department\nIIT Bombay - Powai, Mumbai 400076\nhelpdesk@e-yantra.org");
data.put(m130.getName(), m130);
Marker m131 = new Room("Machine Lab", "Mach. Lab", 1445, 1669, 12,
"N2 Bay", "Near",
"Comes under Electrical Engineering Department\n+912225764422");
data.put(m131.getName(), m131);
Marker m132 = new Room("Machine Tool Lab", "Mach. Tool Lab", 4410,
1740, 12, "S2 Bay", "Near",
"Comes under Mechanical Engineering Department\n+912225764518 / +912225764537");
data.put(m132.getName(), m132);
Marker m133 = new Room("Metal Forming Lab", "0", 4290, 1470, 12,
"Structural Evaluation & Material Technologies Lab", "Near",
"Comes under Mechanical Engineering Department\n+912225764561");
data.put(m133.getName(), m133);
Marker m134 = new Building("Micro Fluidics Lab", "0", 4620, 1783, 12,
new String[] { "RM Lab (Rapid manufacturing)" }, "");
data.put(m134.getName(), m134);
Marker m135 = new Room("N1 Bay", "0", 4525, 1680, 1,
"SMAmL Suman Mashruwala Advanced Microengineering Lab", "Near",
"Comes under Chemical Engineering Department\n+912225764211");
data.put(m135.getName(), m135);
Marker m136 = new Room("N2 Bay", "0", 4445, 1669, 1,
"SMAmL Suman Mashruwala Advanced Microengineering Lab", "Near",
"");
data.put(m136.getName(), m136);
Marker m137 = new Room("N3 Bay", "0", 4360, 1645, 1,
"SMAmL Suman Mashruwala Advanced Microengineering Lab", "Near",
"");
data.put(m137.getName(), m137);
Marker m138 = new Building("National Geotechnical Centrifuge Facility",
"GeoTech Centrifuge", 4370, 1395, 1,
new String[] { "Centrifugal Lab" }, "");
data.put(m138.getName(), m138);
Marker m139 = new Marker("OrthoCad Lab", "0", 4683, 1702, 12,
"Comes under Mechanical Engineering Department\n+912225764399");
data.put(m139.getName(), m139);
Marker m140 = new Room("Old ONGC Lab", "0", 4275, 1555, 12,
"IC Engine and Combustion Lab", "Near", "");
data.put(m140.getName(), m140);
Marker m141 = new Building("Physics Lab (Ist Years)", "Phy Lab (1 Yr)",
4585, 1540, 12, new String[] { "UG Lab (Ist Years)" },
"Comes under Physics department");
data.put(m141.getName(), m141);
Marker m142 = new Room("Refrigeration, A/C and Cryogenics Lab", "0",
4225, 1630, 12, "Treelabs", "Near",
"Comes under Mechanical Engineering Department\n+912225764587");
data.put(m142.getName(), m142);
Marker m143 = new Room("RM Lab (Rapid manufacturing)", "RM Lab", 4650,
1757, 12, "Micro Fluidics Lab", "Near", "");
data.put(m143.getName(), m143);
Marker m144 = new Room("Rock Cutting Lab", "0", 3921, 2095, 12,
"Rock Powdering Lab", "Near", "");
data.put(m144.getName(), m144);
Marker m145 = new Building("Rock Powdering Lab", "0", 3921, 2095, 12,
new String[] { "Rock Cutting Lab" }, "");
data.put(m145.getName(), m145);
Marker m146 = new Room("S1 Bay", "0", 4490, 1760, 1,
"Structural integrity Testing and Analysis Centre", "Near", "");
data.put(m146.getName(), m146);
Marker m147 = new Room("S2 Bay", "0", 4410, 1740, 1,
"Structural integrity Testing and Analysis Centre", "Near",
"Tel:+912225764213");
data.put(m147.getName(), m147);
Marker m148 = new Room("S3 Bay", "0", 4325, 1720, 1,
"Structural integrity Testing and Analysis Centre", "Near", "");
data.put(m148.getName(), m148);
Marker m149 = new Room(
"Structural Evaluation & Material Technologies Lab",
"SEMT Lab", 4280, 1510, 12, "Hydraulics Lab", "Near",
"Comes under Civil Engineering Department\n+912225764318");
data.put(m149.getName(), m149);
Marker m150 = new Building(
"Structural integrity Testing and Analysis Centre", "SITAC",
4355, 1750, 1, new String[] { "S1 Bay", "S2 Bay", "S3 Bay" },
"Comes under Mechanical Engineering Department\n+912225764528");
data.put(m150.getName(), m150);
Marker m151 = new Room(
"Solar Lab",
"0",
4230,
1435,
12,
"Energy Systems Lab",
"",
"Comes under Chemistry Department\n+912225764887\nSOLAR LAB (308) Phone: +912225764173 ");
data.put(m151.getName(), m151);
Marker m152 = new Room("Steam Power Lab", "0", 4376, 1526, 12,
"Heat Transfer and Thermodynamic Lab", "",
"Comes under Mechanical Engineering Department\n+912225764584");
data.put(m152.getName(), m152);
Marker m153 = new Building(
"SMAmL Suman Mashruwala Advanced Microengineering Lab",
"Adv. MicroEngg Lab",
4431,
1615,
12,
new String[] { "N1 Bay", "N2 Bay", "N3 Bay" },
"Phone: +912225767519 / +912225764534\nFax:-+912225726875\nE-mail: gandhi@me.iitb.ac.in");
data.put(m153.getName(), m153);
Marker m154 = new Room(
"Supercritical fluid Processing facility (Chemical Engg.)",
"Fluid Processing", 4490, 1760, 1, "S1 Bay", "",
"Comes under Chemical Engineering Department\n+912225767201 / +912225767202");
data.put(m154.getName(), m154);
Marker m155 = new Marker(
"Thermal Hydraulic Test Facility",
"Hydraulic Test",
4463,
1536,
1,
"Comes under Mechanical Engineering Department\n+912225762545 Ext. 7500, 7501, 2576 7500, 2576 7501.");
data.put(m155.getName(), m155);
Marker m156 = new Room("Tinkerers Lab (STAB)", "0", 4225, 1630, 12,
"Treelabs", "", "");
data.put(m156.getName(), m156);
Marker m157 = new Building(
"Treelabs",
"0",
4225,
1630,
9,
new String[] { "Bio-diesel Lab", "ENELEK Power Sine",
"IC Engine and Combustion Lab",
"Refrigeration, A/C and Cryogenics Lab",
"Tinkerers Lab (STAB)" },
"TreeLabs is an inventions factory to nurture and encourage inventors and innovations, leading to entrepreneurship\nAddress: Electrical Engineering Dept, \nN-5 Bay (near Mech Engg Dept), \nI.I.T.Bombay, Powai, \nMumbai - 400076, India. \nPhone: +912225723001 / +912225764410\nEmail: Prof. Dipankar : dipankar@iitbombay.org");
data.put(m157.getName(), m157);
Marker m158 = new Room("UG Lab / S2 Bay", "0", 4410, 1740, 12,
"S2 Bay", "",
"Comes under Chemical Engineering Department \n+912225764207");
data.put(m158.getName(), m158);
Marker m159 = new Room("UG Lab (Ist Years)", "0", 4585, 1540, 12,
"Physics Lab (Ist Years)", "", "");
data.put(m159.getName(), m159);
Marker m160 = new Room("Printing and photocopying H11", "Prints", 2987,
1368, 11, "Hostel 11 Athena (Girls Hostel)", "Inside", "");
data.put(m160.getName(), m160);
Marker m161 = new Room("Printing and photocopying H8", "Prints", 2834,
1257, 11, "Hostel 08 Woodland", "Inside", "");
data.put(m161.getName(), m161);
Marker m162 = new Room("Printing and photocopying Main Building",
"Prints", 3628, 1640, 11, "Main Building", "Inside", "");
data.put(m162.getName(), m162);
Marker m163 = new Marker("ATM - State Bank main gate", "SBI ATM", 2164,
3227, 6, "");
data.put(m163.getName(), m163);
Marker m164 = new Room("KReSIT Canteen", "KReSIT Canteen", 3301, 2106,
5, "Kanwal Rekhi School of Information Technology ", "Inside",
"From 10 to 8. Samosas run out by 5:30ish though!");
data.put(m164.getName(), m164);
Marker m165 = new Room(
"IDC Canteen",
"IDC Cant.",
4207,
1732,
5,
"Industrial Design Centre",
"Inside",
"Santosh bhaiyas Canteen +918652423193\n9am to 5:30 pm, weekdays only\nMenu: Tea, Coffee, Upma, Poha, Idli Chutney, Meduwada, Samosa, manchurian roll, paneer roll, chicken roll, Vada Paav, biscuits, Maggi, Tropicana, cold drinks");
data.put(m165.getName(), m165);
Marker m166 = new Room(
"IDC Shakti",
"Shakti",
4207,
1732,
5,
"Industrial Design Centre",
"Inside",
"Piping hot, home style food between 1 pm and 2:30 pm, weekdays only!\nCall Mr. Gaikwad to order a tiffin at +919833575881");
data.put(m166.getName(), m166);
Marker m167 = new Room("H13 Night Canteen", "H13 Night Cant.", 1918,
745, 5, "Hostel 13 House of Titans", "Inside",
"Open till 3 am, recomended for night-outs!");
data.put(m167.getName(), m167);
Marker m168 = new Room(
"HALL 1 (LA 101)",
"0",
3779,
2220,
4,
"Lecture Hall Complex - 3",
"Ground and First floors",
"The classroom has 4 entrance doors, two on ground floor and two in first floor.");
data.put(m168.getName(), m168);
Marker m169 = new Room(
"HALL 2 (LA 102)",
"0",
3779,
2220,
4,
"Lecture Hall Complex - 3",
"Ground and First floors",
"The classroom has 4 entrance doors, two on ground floor and two in first floor.");
data.put(m169.getName(), m169);
Marker m170 = new Room(
"HALL 3 (LA 103)",
"0",
3779,
2220,
4,
"Lecture Hall Complex - 3",
"Second and Third floors",
"The classroom has 4 entrance doors, two on second floor and two in third floor.");
data.put(m170.getName(), m170);
Marker m171 = new Room(
"HALL 4 (LA 104)",
"0",
3779,
2220,
4,
"Lecture Hall Complex - 3",
"Second and Third floors",
"The classroom has 4 entrance doors, two on second floor and two in third floor.");
data.put(m171.getName(), m171);
Marker m172 = new Room("LT 001 (LCT 01)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "Ground floor", "");
data.put(m172.getName(), m172);
Marker m173 = new Room("LT 002 (LCT 02)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "Ground floor", "");
data.put(m173.getName(), m173);
Marker m174 = new Room("LT 003 (LCT 03)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "Ground floor", "");
data.put(m174.getName(), m174);
Marker m175 = new Room("LT 004 (LCT 04)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "Ground floor", "");
data.put(m175.getName(), m175);
Marker m176 = new Room("LT 005 (LCT 05)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "Ground floor", "");
data.put(m176.getName(), m176);
Marker m177 = new Room("LT 006 (LCT 06)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "Ground floor", "");
data.put(m177.getName(), m177);
Marker m178 = new Room("LT 101 (LCT 11)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "First floor", "");
data.put(m178.getName(), m178);
Marker m179 = new Room("LT 102 (LCT 12)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "First floor", "");
data.put(m179.getName(), m179);
Marker m180 = new Room("LT 103 (LCT 13)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "First floor", "");
data.put(m180.getName(), m180);
Marker m181 = new Room("LT 104 (LCT 14)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "First floor", "");
data.put(m181.getName(), m181);
Marker m182 = new Room("LT 105 (LCT 15)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "First floor", "");
data.put(m182.getName(), m182);
Marker m183 = new Room("LT 106 (LCT 16)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "First floor", "");
data.put(m183.getName(), m183);
Marker m184 = new Room("LT 201 (LCT 21)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "Second floor", "");
data.put(m184.getName(), m184);
Marker m185 = new Room("LT 202 (LCT 22)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "Second floor", "");
data.put(m185.getName(), m185);
Marker m186 = new Room("LT 203 (LCT 23)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "Second floor", "");
data.put(m186.getName(), m186);
Marker m187 = new Room("LT 204 (LCT 24)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "Second floor", "");
data.put(m187.getName(), m187);
Marker m188 = new Room("LT 205 (LCT 25)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "Second floor", "");
data.put(m188.getName(), m188);
Marker m189 = new Room("LT 206 (LCT 26)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "Second floor", "");
data.put(m189.getName(), m189);
Marker m190 = new Room("LT 301 (LCT 31)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "Third floor", "");
data.put(m190.getName(), m190);
Marker m191 = new Room("LT 302 (LCT 32)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "Third floor", "");
data.put(m191.getName(), m191);
Marker m192 = new Room("LT 303 (LCT 33)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "Third floor", "");
data.put(m192.getName(), m192);
Marker m193 = new Room("LT 304 (LCT 34)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "Third floor", "");
data.put(m193.getName(), m193);
Marker m194 = new Room("LT 305 (LCT 35)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "Third floor", "");
data.put(m194.getName(), m194);
Marker m195 = new Room("LT 306 (LCT 36)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "Third floor", "");
data.put(m195.getName(), m195);
Marker m196 = new Room("LC 001 (LCC 1)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "Ground floor", "");
data.put(m196.getName(), m196);
Marker m197 = new Room("LC 002 (LCC 2)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "Ground floor", "");
data.put(m197.getName(), m197);
Marker m198 = new Room("LC 101 (LCC 11)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "First floor", "");
data.put(m198.getName(), m198);
Marker m199 = new Room("LC 102 (LCC 12)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "First floor", "");
data.put(m199.getName(), m199);
Marker m200 = new Room("LC 201 (LCC 21)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "Second floor", "");
data.put(m200.getName(), m200);
Marker m201 = new Room("LC 202 (LCC 22)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "Second floor", "");
data.put(m201.getName(), m201);
Marker m202 = new Room("LC 301 (LCC 31)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "Third floor", "");
data.put(m202.getName(), m202);
Marker m203 = new Room("LC 302 (LCC 32)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "Third floor", "");
data.put(m203.getName(), m203);
Marker m204 = new Room("LH 101 (LCH 11)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "First floor", "");
data.put(m204.getName(), m204);
Marker m205 = new Room("LH 102 (LCH 12)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "First floor", "");
data.put(m205.getName(), m205);
Marker m206 = new Room("LH 301 (LCH 31)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "Third floor", "");
data.put(m206.getName(), m206);
Marker m207 = new Room("LH 302 (LCH 32)", "0", 3570, 2152, 4,
"Lecture Hall Complex - 1 & 2", "Third floor", "");
data.put(m207.getName(), m207);
Marker m208 = new Room("New Software Lab", "NSL", 4002, 1545, 12,
"Old Computer Science Engineering Department", "Ground floor",
"");
data.put(m208.getName(), m208);
Marker m209 = new Room("Old Software Lab", "OSL", 3928, 1496, 12,
"Mathematics Department", "Ground floor", "");
data.put(m209.getName(), m209);
Marker m210 = new Marker(
"Inter-disciplinary Programme in Systems and Control Engineering",
"IDP Sys & Cntrl Engg.",
4011,
1411,
1,
"http://www.sc.iitb.ac.in\nTel: +912225767884, +912225722545\nFax:+912225720057\nM Tech and Ph D offered in this programme. Research ares include nonlinear control, robotics, path-planning, embedded control, coordination of autonomous vehicles, multi-agent systems, game theory, information theory, combinatorics, sliding mode control and applications, fractional-order modelling and control, optimization and optimization-based control, and stochastic processes. In addition, research in the areas of process control, identification, behavioural theory, matrix computation, automotive control are being pursued by the associate faculty members. ");
data.put(m210.getName(), m210);
Marker m211 = new Room(
"WRCBB Wadhwani Research Centre in Biosciences and Bioengineering ",
"Wadhwani Research Centre BB", 3934, 2241, 1,
"Biosciences and Bioengineering Department", "Inside", "");
data.put(m211.getName(), m211);
Marker m212 = new Room(
"Aerospace Engineering Annexe",
"Aero Annx",
3911,
2171,
1,
"Humanities and Social Sciences Department",
"Inside",
"http://www.aero.iitb.ac.in\nPhone No.: +912225764111\nFax No.: +912225722602.\nEmail: office@aero.iitb.ac.in \nThe department offers academic programs for B. Tech, M. Tech, Ph. D. Specialization are offered: Aerodynamics, Control and Guidance, Propulsion, Structures, and Systems Engineering");
data.put(m212.getName(), m212);
Marker m213 = new Room("Open Air Theatre", "OAT", 3599, 1225, 8,
"Students Activity Centre", "Inside", "Tel: +912225768968");
data.put(m213.getName(), m213);
Marker m214 = new Room(
"Inter-disciplinary Programme in Educational Technology",
"IDP Edu Tech",
3928,
1496,
1,
"Mathematics Department",
"Inside",
"http://www.et.iitb.ac.in\nMain Office: Mathematics Building, Near Central Library.\nTel:+912225764820\nFax: +912225764812\nPh.D. is offered in this programme. Research areas include Pan-Domain Cognitive Abilities, Teacher Use of Educational Technology Tools and Strategies, Educational Technology Tools.");
data.put(m214.getName(), m214);
Marker m215 = new Room(
"Inter-disciplinary Programme in Climate Studies",
"IDP Climate Studies",
3879,
1804,
1,
"Civil Engineering Department",
"Inside",
"http://www.climate.iitb.ac.in\nOffice inside Civil Engineering building\nTel:+912225767301\nFax:+912225767302\nPh.D. is offered in this programme. Research areas include Climate science and technology, Technology evaluation and assessment, Impacts, Vulnerability and Adaptation");
data.put(m215.getName(), m215);
Marker m216 = new Room(
"Inter-disciplinary Programme in Corrosion Science & Engineering",
"IDP Corro Sci & Engg",
3631,
2044,
1,
"Metallurgical Engineering and Material Science Department",
"Inside",
"http://www.iitb.ac.in/~corrsci\nOffice inside Metallurgical Engineering and Material Science building\nTel: +912225767601 / +912225767602\nPh. D and M.Tech offered in this programme. Research focuses on corrosion and its control with applications in industris such as Oil and gas industry, Marine and aerospace industry, Automobile industry, Building and constructions, General engineering industry, Power plants, etc.");
data.put(m216.getName(), m216);
Marker m217 = new Room(
"Industrial Engineering and Operations Research",
"IDP IEOR",
4009,
1645,
1,
"Mechanical Engineering Department",
"Inside",
"http://www.ieor.iitb.ac.in\nRoom 308A, Mechanical Engineering Building,\nIndian Institute of Technology Bombay,\nPowai, Mumbai (INDIA), PIN: 400076, \nFax: +912225726875, +912225723480\nM.Tech, Dual Degree (MSc-PhD) and PhD offered in this programme. Research areas include Optimization: Models, theory and algorithms, Stochastic models, Stochastic control, Simulation Modeling and Analysis, Artificial Intelligence based methods, Game theory, Logistics and Transportation, Supply Chain, Analysis and Inventory Planning, Financial Engineering, Optimization, Planning and Control in Manufacturing and Robotics, Scheduling and ERP");
data.put(m217.getName(), m217);
Marker m218 = new Room("Aqueous corrosion lab", "Aq Corro Lab", 3631,
2044, 12,
"Metallurgical Engineering and Material Science Department",
"Inside", "Tel: +912225764607");
data.put(m218.getName(), m218);
Marker m219 = new Room("Corrosion lab I", "Corro Lab I", 3631, 2044,
12,
"Metallurgical Engineering and Material Science Department",
"Inside", "Tel: +912225764618");
data.put(m219.getName(), m219);
Marker m220 = new Room("Corrosion science paint lab",
"Corro Sci Paint Lab", 3631, 2044, 12,
"Metallurgical Engineering and Material Science Department",
"Inside", "Tel: +912225764606");
data.put(m220.getName(), m220);
Marker m221 = new Room(
"Kindergarten School",
"K.G. School",
3331,
2865,
7,
"Campus School",
"Inside",
"Principal: Ms. Lata P. Jagdeesh\nhttp://www.iitb.ac.in/facilities/kgschool\nSchool Office: +912225768991\nIn Charges Office: +912225768913\nEmail: kgschool@iitb.ac.in\nIn 1963 for the benefit of the children of the staff members staying in the campus of IIT Bombay, a School consisting of K.G. and primary classes commenced functioning from 10th June 1963. This School had one Nursery class, one Kindergarten class and one class each of I and II (4 classes). From a small number of 53 students at the start today the School has 250 children on roll, 7 teaching staff, 12 supporting staff and one office staff working with the School In Charge.\n");
data.put(m221.getName(), m221);
Marker m222 = new Marker(
"Society for Applied Microwave Electronics Engineering & Research",
"SAMEER ",
4538,
837,
1,
"http://www.sameer.gov.in\nPhone: +912225727100\nFax: +912225723254\nSAMEER was set up as an autonomous R & D laboratory at Mumbai under the then Department of Electronics, Government of India with a broad mandate to undertake R & D work in the areas of Microwave Engineering and Electromagnetic Engineering Technology. It is an offshoot of the special microwave products unit (SMPU) set up in 1977 at the TATA INSTITUTE OF FUNDAMENTAL RESEARCH (TIFR), Mumbai. SAMEER, Mumbai was setup in 1984.");
data.put(m222.getName(), m222);
Marker m223 = new Marker("Sameer Hill", "0", 4830, 675, 9, "");
data.put(m223.getName(), m223);
Marker m224 = new Marker("C22, A wing, Sahyadri", "Sahyadri", 4673,
1077, 3, "Hill side, Flat nos. 151 - 168");
data.put(m224.getName(), m224);
Marker m225 = new Marker("B21 Satpura ", "B 21", 3332, 2602, 3, "");
data.put(m225.getName(), m225);
Marker m226 = new Marker(
"Girish Gaitonde Building",
"GG Bldg",
3668,
1937,
1,
"Contact persons:\nMadhumati Shetty +912225767401\nVaishali Deshpande +912225767402\nSantosh S. Kharat +912225767402\nTanvi D. Shelatkar +912225767402");
data.put(m226.getName(), m226);
Marker m227 = new Marker(
"Uphar",
"0",
4052,
2815,
5,
"Upkar food joint\nBreakfast: 6:30 am to 12 pm\nLunch: 12pm to 3 pm\nEvening snacks: 4 pm to 7:30 pm");
data.put(m227.getName(), m227);
Marker m228 = new Marker("Campus Hub", "0", 2815, 1067, 5,
"Tel:+912264909044\nOpen from 8:00 am - 1:00 am");
data.put(m228.getName(), m228);
Marker m229 = new Marker("C22, B wing, Vindya", "Vindya", 4646, 1110,
3, "Hill side, Flat nos. 169 - 186");
data.put(m229.getName(), m229);
Marker m230 = new Marker("Tulsi A", "0", 4515, 952, 3, "PS Quarters");
data.put(m230.getName(), m230);
Marker m231 = new Marker("Tulsi B", "0", 4573, 987, 3, "PS Quarters");
data.put(m231.getName(), m231);
Marker m232 = new Marker("Tulsi C", "0", 4607, 1031, 3, "PS Quarters");
data.put(m232.getName(), m232);
Marker m233 = new Marker("Type 2B 1 ", "0", 4421, 2264, 3,
"2B-Type Quarters, Flat nos 1 - 6");
data.put(m233.getName(), m233);
Marker m234 = new Marker("Type 2B 2", "0", 4381, 2311, 3,
"2B-Type Quarters, Flat nos 7 - 12");
data.put(m234.getName(), m234);
Marker m235 = new Marker("Type 2B 3", "0", 4331, 2388, 3,
"2B-Type Quarters, Flat nos 13 - 18");
data.put(m235.getName(), m235);
Marker m236 = new Marker("Type 2B 4", "0", 4284, 2462, 3,
"2B-Type Quarters, Flat nos 19 - 24");
data.put(m236.getName(), m236);
Marker m237 = new Marker("Type 2B 5", "0", 4196, 2455, 3,
"2B-Type Quarters, Flat nos 25 - 30");
data.put(m237.getName(), m237);
Marker m238 = new Marker("Type 2B 6", "0", 4243, 2391, 3,
"2B-Type Quarters, Flat nos 31 - 36");
data.put(m238.getName(), m238);
Marker m239 = new Marker("Type 2B 7", "0", 4296, 2312, 3,
"2B-Type Quarters, Flat nos 37 - 42");
data.put(m239.getName(), m239);
Marker m240 = new Marker("Type 2B 8", "0", 4348, 2247, 3,
"2B-Type Quarters, Flat nos 43 - 48");
data.put(m240.getName(), m240);
Marker m241 = new Marker("Type 2B 9", "0", 4384, 2192, 3,
"2B-Type Quarters, Flat nos 49 - 54");
data.put(m241.getName(), m241);
Marker m242 = new Marker("Type 2B 11", "0", 808, 2612, 3,
"2B-Type Quarters, Flat nos 61 - 66");
data.put(m242.getName(), m242);
Marker m243 = new Marker("Type 2B 12", "0", 701, 2615, 3,
"2B-Type Quarters, Flat nos 67 - 72");
data.put(m243.getName(), m243);
Marker m244 = new Marker("Type 2B 13", "0", 691, 2555, 3,
"2B-Type Quarters, Flat nos 73 - 78");
data.put(m244.getName(), m244);
Marker m245 = new Marker("Type 2B 14", "0", 1144, 2866, 3,
"2B-Type Quarters, Flat nos 79 - 84");
data.put(m245.getName(), m245);
Marker m246 = new Marker("Type 2B 15", "0", 1076, 2833, 3,
"2B-Type Quarters, Flat nos 85 - 90");
data.put(m246.getName(), m246);
Marker m247 = new Marker("Type 2B 16", "0", 908, 2798, 3,
"2B-Type Quarters, Flat nos 91 - 96");
data.put(m247.getName(), m247);
Marker m248 = new Marker("Type 2B 17", "0", 878, 2756, 3,
"2B-Type Quarters, Flat nos 97 - 102");
data.put(m248.getName(), m248);
Marker m249 = new Marker("Type 2B 18", "0", 615, 2492, 3,
"2B-Type Quarters, Flat nos 103 - 108");
data.put(m249.getName(), m249);
Marker m250 = new Marker("Type 2B 19", "0", 2573, 2468, 3,
"2B-Type Quarters, Flat nos 109 - 114");
data.put(m250.getName(), m250);
Marker m251 = new Marker("Type 2B 20", "0", 4786, 1431, 3,
"2B-Type Quarters, Flat nos 115 - 134");
data.put(m251.getName(), m251);
Marker m252 = new Marker("Type 2B 21", "0", 4720, 1371, 3,
"2B-Type Quarters, Flat nos 135 - 140");
data.put(m252.getName(), m252);
Marker m253 = new Marker("Type 2B 22", "0", 4761, 1315, 3,
"2B-Type Quarters, Flat nos 141 - 164");
data.put(m253.getName(), m253);
Marker m254 = new Marker("Type 2B 23", "0", 4365, 1180, 3,
"2B-Type Quarters, Flat nos 165 - 192");
data.put(m254.getName(), m254);
Marker m255 = new Marker("Type 2B 24", "0", 4124, 1238, 3,
"2B-Type Quarters, Flat nos 193 - 220");
data.put(m255.getName(), m255);
Marker m256 = new Marker("Bungalow A2 ", "A2", 2491, 2581, 3,
"A-Type Bungalow");
data.put(m256.getName(), m256);
Marker m257 = new Marker("Bungalow A3 ", "A3", 2415, 2682, 3,
"A-Type Bungalow");
data.put(m257.getName(), m257);
Marker m258 = new Marker("Bungalow A4 ", "A4", 2373, 2767, 3,
"A-Type Bungalow");
data.put(m258.getName(), m258);
Marker m259 = new Marker("Bungalow A5 ", "A5", 2319, 2848, 3,
"A-Type Bungalow");
data.put(m259.getName(), m259);
Marker m260 = new Marker("Bungalow A6 ", "A6", 2254, 2963, 3,
"A-Type Bungalow");
data.put(m260.getName(), m260);
Marker m261 = new Marker("Bungalow A7 ", "A7", 2211, 3055, 3,
"A-Type Bungalow");
data.put(m261.getName(), m261);
Marker m262 = new Marker("Bungalow A8 ", "A8", 2176, 3135, 3,
"A-Type Bungalow");
data.put(m262.getName(), m262);
Marker m263 = new Marker("Bungalow A9 ", "A9", 1888, 2960, 3,
"A-Type Bungalow");
data.put(m263.getName(), m263);
Marker m264 = new Marker("Bungalow A10 ", "A10", 1962, 2928, 3,
"A-Type Bungalow");
data.put(m264.getName(), m264);
Marker m265 = new Marker("Bungalow A11 ", "A11", 2074, 2885, 3,
"A-Type Bungalow");
data.put(m265.getName(), m265);
Marker m266 = new Marker("Bungalow A12 ", "A12", 2157, 2855, 3,
"A-Type Bungalow");
data.put(m266.getName(), m266);
Marker m267 = new Marker("Bungalow A13 ", "A13", 2536, 2374, 3,
"A-Type Bungalow");
data.put(m267.getName(), m267);
Marker m268 = new Marker("Bungalow A14 ", "A14", 3950, 1273, 3,
"A-Type Bungalow");
data.put(m268.getName(), m268);
Marker m269 = new Marker("Bungalow A15 ", "A15", 4017, 1243, 3,
"A-Type Bungalow");
data.put(m269.getName(), m269);
Marker m270 = new Marker("Bungalow A16 ", "A16", 4085, 1210, 3,
"A-Type Bungalow");
data.put(m270.getName(), m270);
Marker m271 = new Marker("Bungalow A17 ", "A17", 4155, 1175, 3,
"A-Type Bungalow");
data.put(m271.getName(), m271);
Marker m272 = new Marker("Bungalow A18 ", "A18", 4220, 1142, 3,
"A-Type Bungalow");
data.put(m272.getName(), m272);
Marker m273 = new Marker("Bungalow A19 ", "A19", 4280, 1110, 3,
"A-Type Bungalow");
data.put(m273.getName(), m273);
Marker m274 = new Marker("Type B-1", "B1", 2680, 2368, 3,
"B-Type Quarters Flat nos. 1 - 6");
data.put(m274.getName(), m274);
Marker m275 = new Marker("Type B-2", "B2", 2848, 2685, 3,
"B-Type Quarters Flat nos. 7 - 10");
data.put(m275.getName(), m275);
Marker m276 = new Marker("Type B-3", "B3", 2797, 2820, 3,
"B-Type Quarters Flat nos. 11 - 14");
data.put(m276.getName(), m276);
Marker m277 = new Marker("Type B-4", "B4", 2743, 2947, 3,
"B-Type Quarters Flat nos. 15 - 18");
data.put(m277.getName(), m277);
Marker m278 = new Marker("Type B-5", "B5", 2687, 3079, 3,
"B-Type Quarters Flat nos. 19 - 22");
data.put(m278.getName(), m278);
Marker m279 = new Marker("Type B-6", "B6", 2508, 3189, 3,
"B-Type Quarters Flat nos. 23 - 26");
data.put(m279.getName(), m279);
Marker m280 = new Marker("Type B-7", "B7", 2529, 3009, 3,
"B-Type Quarters Flat nos. 27 - 30");
data.put(m280.getName(), m280);
Marker m281 = new Marker("Type B-8", "B8", 2600, 2867, 3,
"B-Type Quarters Flat nos. 31 - 34");
data.put(m281.getName(), m281);
Marker m282 = new Marker("Type B-9", "B9", 2653, 2748, 3,
"B-Type Quarters Flat nos. 35 - 38");
data.put(m282.getName(), m282);
Marker m283 = new Marker("Type B-10", "B10", 2726, 2634, 3,
"B-Type Quarters Flat nos. 39 - 42");
data.put(m283.getName(), m283);
Marker m284 = new Marker("Type B-11", "B11", 2232, 2552, 3,
"B-Type Quarters Flat nos. 43 - 46");
data.put(m284.getName(), m284);
Marker m285 = new Marker("Type B-12", "B12", 2080, 2631, 3,
"B-Type Quarters Flat nos. 47 - 50");
data.put(m285.getName(), m285);
Marker m286 = new Marker("Type B-13", "B13", 2356, 2478, 3,
"B-Type Quarters Flat nos. 51 - 54");
data.put(m286.getName(), m286);
Marker m287 = new Marker("Type B-14", "B14", 2470, 2291, 3,
"B-Type Quarters Flat nos. 55 - 58");
data.put(m287.getName(), m287);
Marker m288 = new Marker("Type B-15", "B15", 2192, 2665, 3,
"B-Type Quarters Flat nos. 59 - 62");
data.put(m288.getName(), m288);
Marker m289 = new Marker("Type B-16", "B16", 2085, 2719, 3,
"B-Type Quarters Flat nos. 63 - 66");
data.put(m289.getName(), m289);
Marker m290 = new Marker("Type B-17", "B17", 3040, 2461, 3,
"B-Type Quarters Flat nos. 67 - 72");
data.put(m290.getName(), m290);
Marker m291 = new Marker("Type B-18", "B18", 3159, 2368, 3,
"B-Type Quarters Flat nos. 73 - 74 and 73A - 74A ");
data.put(m291.getName(), m291);
Marker m292 = new Marker("BTR Building - A & B", "BTR A & B", 2002,
3087, 3, "A new Type B building is proposed here.");
data.put(m292.getName(), m292);
Marker m293 = new Marker("Type C-2", "C2", 3108, 2552, 3,
"C-Type Quarters Flat nos. 13 - 18");
data.put(m293.getName(), m293);
Marker m294 = new Marker("Type C-5", "C5", 3464, 2708, 3,
"C-Type Quarters Flat nos. 31 - 36");
data.put(m294.getName(), m294);
Marker m295 = new Marker("Type C-6", "C6", 3547, 2771, 3,
"C-Type Quarters Flat nos. 37 - 42");
data.put(m295.getName(), m295);
Marker m296 = new Marker("Type C-7", "C7", 3440, 2787, 3,
"C-Type Quarters Flat nos. 43 - 48");
data.put(m296.getName(), m296);
Marker m297 = new Marker("Type C-8", "C8", 3078, 2878, 3,
"C-Type Quarters Flat nos. 49 - 54");
data.put(m297.getName(), m297);
Marker m298 = new Marker("Type C-9", "C9", 2904, 2910, 3,
"C-Type Quarters Flat nos. 55 - 60");
data.put(m298.getName(), m298);
Marker m299 = new Marker("Type C-10", "C10", 2944, 2820, 3,
"C-Type Quarters Flat nos. 61 - 66");
data.put(m299.getName(), m299);
Marker m300 = new Marker("Type C-11", "C11", 2832, 3131, 3,
"C-Type Quarters Flat nos. 67 - 72");
data.put(m300.getName(), m300);
Marker m301 = new Marker("Type C-12", "C12", 2867, 3006, 3,
"C-Type Quarters Flat nos. 73 - 78");
data.put(m301.getName(), m301);
Marker m302 = new Marker("Type C-13", "C13", 2974, 3070, 3,
"C-Type Quarters Flat nos. 79 - 84");
data.put(m302.getName(), m302);
Marker m303 = new Marker("Type C-14", "C14", 3140, 3047, 3,
"C-Type Quarters Flat nos. 85 - 90");
data.put(m303.getName(), m303);
Marker m304 = new Marker("Type C-15", "C15", 3360, 3033, 3,
"C-Type Quarters Flat nos. 91 - 96");
data.put(m304.getName(), m304);
Marker m305 = new Marker("Type C-16", "C16", 3162, 2991, 3,
"C-Type Quarters Flat nos. 97 - 102");
data.put(m305.getName(), m305);
Marker m306 = new Marker("Type C-17", "C17", 3453, 2987, 3,
"C-Type Quarters Flat nos. 103 - 108");
data.put(m306.getName(), m306);
Marker m307 = new Marker("Type C-18", "C18", 3537, 2963, 3,
"C-Type Quarters Flat nos. 109 - 114");
data.put(m307.getName(), m307);
Marker m308 = new Marker("CSRE A", "0", 4283, 1163, 3,
"CSRE Quarters C139, C140, C143. C144. C147, C148");
data.put(m308.getName(), m308);
Marker m309 = new Marker("CTR 19", "0", 1815, 3040, 3,
"CTR Quarters Flat nos. 115 - 126");
data.put(m309.getName(), m309);
Marker m310 = new Marker("CTR 20", "0", 1749, 2959, 3,
"CTR Quarters Flat nos. 127 - 138");
data.put(m310.getName(), m310);
Marker m311 = new Marker("Type H1 - 1", "1- H1", 866, 2684, 3,
"H1 Type Quarters Flat nos. 1 - 12");
data.put(m311.getName(), m311);
Marker m312 = new Marker("Type H1 - 2", "2-H1", 910, 2613, 3,
"H1 Type Quarters Flat nos. 13 - 24");
data.put(m312.getName(), m312);
Marker m313 = new Marker("Type H1 - 3", "3-H1", 867, 2575, 3,
"H1 Type Quarters Flat nos. 25 - 36");
data.put(m313.getName(), m313);
Marker m314 = new Marker("Type H1 - 4", "4-H1", 812, 2560, 3,
"H1 Type Quarters Flat nos. 37 - 48");
data.put(m314.getName(), m314);
Marker m315 = new Marker("Type H1 - 5", "5-H1", 4552, 1173, 3,
"H1 Type Quarters Flat nos. 49 - 60");
data.put(m315.getName(), m315);
Marker m316 = new Marker("Type H1 - 6", "6- H1", 4468, 1189, 3,
"H1 Type Quarters Flat nos. 61 - 72");
data.put(m316.getName(), m316);
Marker m317 = new Marker("Type H1 - 7", "7-H1", 4542, 1238, 3,
"H1 Type Quarters Flat nos. 73 - 84");
data.put(m317.getName(), m317);
Marker m318 = new Marker("Type H1 - 8", "8- H1", 4442, 1239, 3,
"H1 Type Quarters Flat nos. 85 - 96");
data.put(m318.getName(), m318);
Marker m319 = new Marker("Type H1 - 9", "9-H1", 640, 2329, 3,
"H1 Type Quarters Flat nos. 97 - 108");
data.put(m319.getName(), m319);
Marker m320 = new Marker("Type H1 - 10", "10-H1", 703, 2275, 3,
"H1 Type Quarters Flat nos. 109 - 120");
data.put(m320.getName(), m320);
Marker m321 = new Marker("Type H1 - 11", "11-H1", 849, 2249, 3,
"H1 Type Quarters Flat nos. 121 - 134");
data.put(m321.getName(), m321);
Marker m322 = new Marker("Type H1 - 12", "12-H1", 4747, 1173, 3,
"H1 Type Quarters Flat nos. 135 - 151");
data.put(m322.getName(), m322);
Marker m323 = new Marker("Type H1 - 13", "13- H1", 4786, 1218, 3,
"H1 Type Quarters Flat nos. 152 - 168");
data.put(m323.getName(), m323);
Marker m324 = new Marker("Type H1 - 14", "14-H1", 4645, 1407, 3,
"H1 Type Quarters Flat nos. 169 - 176 and 1A - 2A");
data.put(m324.getName(), m324);
Marker m325 = new Marker("Type H1 - BB", "BB-H1", 921, 2122, 3,
"H1 BB Type Quarters Flat nos. 1 - 26");
data.put(m325.getName(), m325);
Marker m326 = new Marker("Type H2 1", "1-H2", 1257, 2812, 3,
"H2 Type Quarters Flat nos. 1 - 8");
data.put(m326.getName(), m326);
Marker m327 = new Marker("Type H2 - 2", "2-H2", 1344, 2832, 3,
"H2 Type Quarters Flat nos. 9 - 16");
data.put(m327.getName(), m327);
Marker m328 = new Marker("Type H2 - 3", "3-H2", 1417, 2797, 3,
"H2 Type Quarters Flat nos. 17 - 24");
data.put(m328.getName(), m328);
Marker m329 = new Marker("Type H2 - 4", "4-H2", 1187, 2785, 3,
"H2 Type Quarters Flat nos. 25 - 32");
data.put(m329.getName(), m329);
Marker m330 = new Marker("Type H2 - 5", "5-H2", 1302, 2738, 3,
"H2 Type Quarters Flat nos. 33 - 40");
data.put(m330.getName(), m330);
Marker m331 = new Marker("Type H2 - 6", "6-H2", 1101, 2774, 3,
"H2 Type Quarters Flat nos. 41 - 48");
data.put(m331.getName(), m331);
Marker m332 = new Marker("Type H2 - 7", "7-H2", 1211, 2702, 3,
"H2 Type Quarters Flat nos. 49 - 56");
data.put(m332.getName(), m332);
Marker m333 = new Marker("Type H2 - 8", "8-H2", 1059, 2719, 3,
"H2 Type Quarters Flat nos. 57 - 64");
data.put(m333.getName(), m333);
Marker m334 = new Marker("Type H2 - 9", "9-H2", 1145, 2682, 3,
"H2 Type Quarters Flat nos. 65 - 72");
data.put(m334.getName(), m334);
Marker m335 = new Marker("Type H2 - 10", "10-H2", 978, 2702, 3,
"H2 Type Quarters Flat nos. 73 - 80");
data.put(m335.getName(), m335);
Marker m336 = new Marker("Type H2 - 11", "11-H2", 1049, 2666, 3,
"H2 Type Quarters Flat nos. 81 - 88");
data.put(m336.getName(), m336);
Marker m337 = new Marker("Type H2 - 12", "12-H2", 960, 2640, 3,
"H2 Type Quarters Flat nos. 89 - 96");
data.put(m337.getName(), m337);
Marker m338 = new Marker("Type H2 - 13", "13-H2", 753, 2520, 3,
"H2 Type Quarters Flat nos. 97 - 104");
data.put(m338.getName(), m338);
Marker m339 = new Marker("Type H2 - 14", "14-H2", 717, 2510, 3,
"H2 Type Quarters Flat nos. 105 - 112");
data.put(m339.getName(), m339);
Marker m340 = new Marker("Type H2 - 15", "15-H2", 695, 2461, 3,
"H2 Type Quarters Flat nos. 113 - 120");
data.put(m340.getName(), m340);
Marker m341 = new Marker("Type H2 - 16", "16-H2", 774, 2412, 3,
"H2 Type Quarters Flat nos. 121 - 128");
data.put(m341.getName(), m341);
Marker m342 = new Marker("Type H2 - 17", "17-H2", 3110, 1832, 3,
"H2 Type Quarters Flat nos. 129 - 136");
data.put(m342.getName(), m342);
Marker m343 = new Marker("Type H2 - 18", "18-H2", 4451, 1320, 3,
"H2 Type Quarters Flat nos. 137 - 144");
data.put(m343.getName(), m343);
Marker m344 = new Marker("Type H2 - 19", "19-H2", 4377, 1329, 3,
"H2 Type Quarters Flat nos. 145 - 152");
data.put(m344.getName(), m344);
Marker m345 = new Marker("Type H2 - 20", "20-H2", 4307, 1320, 3,
"H2 Type Quarters Flat nos. 153 - 160");
data.put(m345.getName(), m345);
Marker m346 = new Marker("Type H2 - 21", "21-H2", 4304, 1260, 3,
"H2 Type Quarters Flat nos. 161 - 168");
data.put(m346.getName(), m346);
Marker m347 = new Marker("Type H2 - 22", "22-H2", 4231, 1259, 3,
"H2 Type Quarters Flat nos. 169 - 176");
data.put(m347.getName(), m347);
Marker m348 = new Marker("Type H2 - 24", "23-H2", 522, 2424, 3,
"H2 Type Quarters Flat nos. 185 - 192");
data.put(m348.getName(), m348);
Marker m349 = new Marker("Type H2 - 25", "24-H2", 568, 2377, 3,
"H2 Type Quarters Flat nos. 193 - 200");
data.put(m349.getName(), m349);
Marker m350 = new Marker("Type H2 - 26", "25-H2", 746, 2246, 3,
"H2 Type Quarters Flat nos. 201 - 208");
data.put(m350.getName(), m350);
Marker m351 = new Marker("Type H2 - 27", "26-H2", 793, 2214, 3,
"H2 Type Quarters Flat nos. 209 - 216");
data.put(m351.getName(), m351);
Marker m352 = new Marker("Type H2 - 28", "27-H2", 4193, 1295, 3,
"H2 Type Quarters Flat nos. 217 - 232");
data.put(m352.getName(), m352);
Marker m353 = new Marker("Type H2 - 29", "28-H2", 691, 2410, 3,
"H2 Type Quarters Flat nos. 233 - 248");
data.put(m353.getName(), m353);
Marker m354 = new Marker("Type H2 - BB", "BB-H2", 840, 2180, 3,
"H2 BB Type Quarters Flat nos. 1 - 18");
data.put(m354.getName(), m354);
Marker m355 = new Marker("Kendriya Vidyalay Quarters 1", "KV 1", 3592,
2817, 3, "KV Quarters 1 - 5");
data.put(m355.getName(), m355);
Marker m356 = new Marker("Kendriya Vidyalay Quarters 2", "KV 2", 3498,
2854, 3, "KV Quarters 6 - 11");
data.put(m356.getName(), m356);
Marker m357 = new Marker("MW Quarters 1", "MW 1", 4267, 752, 3,
"MW Quarters 1 - 32");
data.put(m357.getName(), m357);
Marker m358 = new Marker("MW Quarters 2", "MW 2", 4124, 780, 3,
"MW Quarters 33 - 68");
data.put(m358.getName(), m358);
Marker m359 = new Marker("Type1 - 1", "1-Type1", 4113, 2583, 3,
"Type 1 Quarters Flat nos. 1 - 12");
data.put(m359.getName(), m359);
Marker m360 = new Marker("Type1 - 2", "2-Type1", 4214, 2586, 3,
"Type 1 Quarters Flat nos. 13 - 24");
data.put(m360.getName(), m360);
Marker m361 = new Marker("Type1 - 3", "3-Type1", 4177, 2652, 3,
"Type 1 Quarters Flat nos. 25 - 36");
data.put(m361.getName(), m361);
Marker m362 = new Marker("Type1 - 4", "4-Type1", 4067, 2658, 3,
"Type 1 Quarters Flat nos. 37 - 48");
data.put(m362.getName(), m362);
Marker m363 = new Marker("Type1 - 6", "6-Type1", 4660, 1367, 3,
"Type 1 Quarters Flat nos. 61 - 72");
data.put(m363.getName(), m363);
Marker m364 = new Marker("Type1 - 7", "7-Type1", 4600, 1351, 3,
"Type 1 Quarters Flat nos. 73 - 84");
data.put(m364.getName(), m364);
Marker m365 = new Marker("Type1 - 8", "8-Type1", 4616, 1271, 3,
"Type 1 Quarters Flat nos. 85 - 96");
data.put(m365.getName(), m365);
Marker m366 = new Marker("Type1 - 9", "9-Type1", 4675, 1293, 3,
"Type 1 Quarters Flat nos. 97 - 108");
data.put(m366.getName(), m366);
Marker m367 = new Marker("Type1 - 10", "10-Type1", 4373, 758, 3,
"Type 1 Quarters Flat nos. 109 - 120");
data.put(m367.getName(), m367);
Marker m368 = new Marker("Type1 - 11", "11-Type1", 3389, 803, 3,
"Type 1 Quarters Flat nos. 121 - 132");
data.put(m368.getName(), m368);
Marker m369 = new Marker("Type1 - 13", "13-Type1", 4637, 1237, 3,
"Type 1 Quarters Flat nos. 145 - 156");
data.put(m369.getName(), m369);
Marker m370 = new Marker("Type1 - 14", "14-Type1", 4670, 1198, 3,
"Type 1 Quarters Flat nos. 157 - 168");
data.put(m370.getName(), m370);
Marker m371 = new Marker("Type1 - 15", "15-Type1", 3151, 1798, 3,
"Type 1 Quarters Flat nos. 169 - 180");
data.put(m371.getName(), m371);
Marker m372 = new Marker("Type1 - 16", "16-Type1", 4713, 1252, 3,
"Type 1 Quarters Flat nos. 181 - 192");
data.put(m372.getName(), m372);
Marker m373 = new Marker("Type1 - 17", "17-Type1", 4785, 1290, 3,
"Type 1 Quarters Flat nos. 193 - 208");
data.put(m373.getName(), m373);
Marker m374 = new Marker("Type1 - 18", "18-Type1", 4801, 1269, 3,
"Type 1 Quarters Flat nos. 209 - 224");
data.put(m374.getName(), m374);
Marker m375 = new Marker("Type1 - 19", "19-Type1", 4340, 815, 3,
"Type 1 Quarters Flat nos. 225 - 259");
data.put(m375.getName(), m375);
Marker m376 = new Marker("Type1 - 20", "20-Type1", 4328, 871, 3,
"Type 1 Quarters Flat nos. 260 - 289");
data.put(m376.getName(), m376);
Marker m377 = new Marker("Type1 - 21", "21-Type1", 4521, 1346, 3,
"Type 1 Quarters Flat nos. 290 - 309");
data.put(m377.getName(), m377);
Marker m378 = new Marker("Type1 - 22", "22-Type1", 2565, 680, 3,
"Type 1 Quarters Flat nos. 310 - 321\nHostel for married PhD students");
data.put(m378.getName(), m378);
Marker m379 = new Marker("QIP 1", "0", 4830, 1376, 3,
"QIP Quarters Flat nos. 1 - 16");
data.put(m379.getName(), m379);
Marker m380 = new Marker("QIP 2", "0", 4869, 1328, 3,
"QIP Quarters Flat nos. 17 - 35");
data.put(m380.getName(), m380);
Marker m381 = new Marker("CSRE B", "0", 4251, 1179, 3,
"CSRE Quarters C141, C142, C145, C146, C149, C150");
data.put(m381.getName(), m381);
Marker m382 = new Marker("CSRE C", "0", 4270, 1188, 3,
"CSRE Quarters D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12");
data.put(m382.getName(), m382);
Marker m384 = new Room(
"Faqir Chand Kohli Auditorium",
"F.C Kohli",
3301,
2106,
4,
"Kanwal Rekhi School of Information Technology ",
"First floor",
"Named after Faqir Chand Kohli, who is often reffered as Father of Indian Software Industry");
data.put(m384.getName(), m384);
Marker m385 = new Room("Amul Parlour", "0", 2114, 800, 5,
"Hostel 14 Silicon ship", "Outside", "Desserts and drinks");
data.put(m385.getName(), m385);
Marker m386 = new Marker("Type 2B 10", "", 737, 2651, 3, "");
data.put(m386.getName(), m386);
Marker m387 = new Marker("Mess for hostels 12|13|14", "Mess", 2044,
734, 5, "");
data.put(m387.getName(), m387);
Marker m388 = new Room("Institute Music Room", "Music Room", 3255,
1711, 9, "Convocation Hall", "", "");
data.put(m388.getName(), m388);
Marker m389 = new Marker("Proposed Area for Hostels 17&18",
"H17 & H18", 2897, 727, 2, "");
data.put(m389.getName(), m389);
Marker m390 = new Marker("Paspoli Gate no. 4 ", "Paspoli Gate", 2247,
196, 10, "This gate is not used regularly");
data.put(m390.getName(), m390);
Marker m391 = new Marker("Security Check Point", "Check Point", 2744,
399, 10, "");
data.put(m391.getName(), m391);
Marker m392 = new Marker("Proposed Science Park", "Science Park", 2140,
259, 9, "");
data.put(m392.getName(), m392);
Marker m393 = new Marker("Proposed Type H1 Building", "Type H1", 4943,
1193, 3, "");
data.put(m393.getName(), m393);
Marker m394 = new Marker("Proposed Hostel for Project Staff",
"Staff Hostel", 4935, 1391, 3, "");
data.put(m394.getName(), m394);
Marker m395 = new Building(
"Proposed Building for Tata Centre for Technology",
"Tata Centre", 4451, 2173, 9, new String[] {
"Proposed Bio Mechanical Department", "Proposed NCAIR",
"Proposed D.S Foundation", "Proposed Press " }, "");
data.put(m395.getName(), m395);
Marker m396 = new Room("Proposed Bio Mechanical Department",
"Bio Mech", 4451, 2173, 1,
"Proposed Building for Tata Centre for Technology", "inside",
"");
data.put(m396.getName(), m396);
Marker m397 = new Room("Proposed NCAIR", "NCAIR", 4451, 2173, 9,
"Proposed Building for Tata Centre for Technology", "inside",
"");
data.put(m397.getName(), m397);
Marker m398 = new Room("Proposed D.S Foundation", "DSF", 4451, 2173, 9,
"Proposed Building for Tata Centre for Technology", "inside",
"");
data.put(m398.getName(), m398);
Marker m399 = new Room("Proposed Press ", "Press", 4451, 2173, 9,
"Proposed Building for Tata Centre for Technology", "inside",
"");
data.put(m399.getName(), m399);
Marker m400 = new Building("Proposed DESE Building", "DESE", 3979,
2467, 9, new String[] { "Proposed CESE" }, "");
data.put(m400.getName(), m400);
Marker m401 = new Room("Proposed CESE", "CESE", 3979, 2467, 9,
"Proposed DESE Building", "inside", "");
data.put(m401.getName(), m401);
Marker m402 = new Marker("Proposed TypeA Building", "TypeA", 1942,
2646, 3, "");
data.put(m402.getName(), m402);
Marker m403 = new Marker("Guest House 3", "Guest House", 2776, 1936, 9,
"");
data.put(m403.getName(), m403);
Marker m404 = new Marker("National Centre for Mathematics",
"Math Centre", 2890, 1880, 9, "");
data.put(m404.getName(), m404);
Marker m405 = new Marker("Outdoor Sports Facility", "Outdoor Sports",
3294, 1031, 8, "");
data.put(m405.getName(), m405);
Marker m406 = new Marker("Squash Court", "0", 3115, 1485, 8, "");
data.put(m406.getName(), m406);
Marker m407 = new Marker("Basketball Court", "Baskey Court", 3161,
1338, 8, "");
data.put(m407.getName(), m407);
Marker m408 = new Marker("Hockey Ground", "0", 3303, 1368, 8, "");
data.put(m408.getName(), m408);
Marker m409 = new Marker("CSRE D", "0", 4302, 1171, 3,
"CSRE Quarters D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12");
data.put(m409.getName(), m409);
}
}
\ No newline at end of file
package com.mrane.data;
import android.graphics.Color;
import android.graphics.PointF;
import java.util.ArrayList;
import java.util.Arrays;
public class Marker {
private int id;
private String name;
private String shortName;
private PointF point;
private int groupIndex;
private boolean showDefault;
private String description;
private String tag;
private String imageUri;
private int parentId;
private String parentRel;
private int[] childIds;
private long lat;
private long lng;
public static final int COLOR_BLUE = Color.rgb(75, 186, 238);
public static final int COLOR_YELLOW = Color.rgb(255, 186, 0);
public static final int COLOR_GREEN = Color.rgb(162, 208, 104);
public static final int COLOR_GRAY = Color.rgb(156, 156, 156);
public static final int DEPARTMENTS = 1;
public static final int HOSTELS = 2;
public static final int RESIDENCES = 3;
public static final int HALLS_N_AUDITORIUMS = 4;
public static final int FOOD_STALLS = 5;
public static final int BANKS_N_ATMS = 6;
public static final int SCHOOLS = 7;
public static final int SPORTS = 8;
public static final int OTHERS = 9;
public static final int GATES = 10;
public static final int PRINT = 11;
public static final int LABS = 12;
private static final String DEPARTMENTS_NAME = "Departments";
private static final String HOSTELS_NAME = "Hostels";
private static final String RESIDENCES_NAME = "Residences";
private static final String HALLS_N_AUDITORIUMS_NAME = "Halls and Auditoriums";
private static final String FOOD_STALLS_NAME = "Food Stalls";
private static final String BANKS_N_ATMS_NAME = "Banks and Atms";
private static final String SCHOOLS_NAME = "Schools";
private static final String SPORTS_NAME = "Sports";
private static final String OTHERS_NAME = "Others";
private static final String GATES_NAME = "Gates";
private static final String PRINT_NAME = "Printer facility";
private static final String LABS_NAME = "Labs";
public Marker(String name, String shortName, float x, float y,
int groupIndex, String description) {
this.setPoint(new PointF(x, y));
this.groupIndex = groupIndex;
this.setName(name);
this.setShortName(shortName);
this.setShowDefault(false);
this.setDescription(description);
this.setImageUri("");
}
public Marker(int id, String name, String shortName, float pixelX, float pixelY,
int groupIndex, String description, int parentId, String parentRel,
int[] childIds, long lat, long lng) {
this.id = id;
this.name = name;
this.shortName = shortName;
this.point = new PointF(pixelX, pixelY);
this.groupIndex = groupIndex;
this.description = description;
this.setParentId(parentId);
this.setParentRel(parentRel);
this.setChildIds(childIds);
this.setLat(lat);
this.setLng(lng);
}
public static int getColor(int group) {
Integer[] yellowGroup = new Integer[] { HOSTELS };
Integer[] blueGroup = new Integer[] { DEPARTMENTS, LABS,
HALLS_N_AUDITORIUMS };
Integer[] greenGroup = new Integer[] { RESIDENCES };
Integer[] purpleGroup = new Integer[] { FOOD_STALLS, BANKS_N_ATMS,
SCHOOLS, SPORTS, OTHERS, GATES, PRINT };
ArrayList<Integer> yellowList = new ArrayList<Integer>(
Arrays.asList(yellowGroup));
ArrayList<Integer> blueList = new ArrayList<Integer>(
Arrays.asList(blueGroup));
ArrayList<Integer> greenList = new ArrayList<Integer>(
Arrays.asList(greenGroup));
ArrayList<Integer> purpleList = new ArrayList<Integer>(
Arrays.asList(purpleGroup));
if (yellowList.contains(group)) {
return COLOR_YELLOW;
} else if (blueList.contains(group)) {
return COLOR_BLUE;
} else if (greenList.contains(group)) {
return COLOR_GREEN;
} else if (purpleList.contains(group)) {
return COLOR_GRAY;
}
return 0;
}
public int getColor() {
int group = this.groupIndex;
return getColor(group);
}
public String getGroupName() {
switch (groupIndex) {
case DEPARTMENTS:
return DEPARTMENTS_NAME;
case HOSTELS:
return HOSTELS_NAME;
case RESIDENCES:
return RESIDENCES_NAME;
case HALLS_N_AUDITORIUMS:
return HALLS_N_AUDITORIUMS_NAME;
case FOOD_STALLS:
return FOOD_STALLS_NAME;
case BANKS_N_ATMS:
return BANKS_N_ATMS_NAME;
case SCHOOLS:
return SCHOOLS_NAME;
case SPORTS:
return SPORTS_NAME;
case OTHERS:
return OTHERS_NAME;
case GATES:
return GATES_NAME;
case PRINT:
return PRINT_NAME;
case LABS:
return LABS_NAME;
}
return "";
}
public static String[] getGroupNames() {
String[] groupNames = { DEPARTMENTS_NAME, LABS_NAME,
HALLS_N_AUDITORIUMS_NAME, HOSTELS_NAME, RESIDENCES_NAME,
FOOD_STALLS_NAME, BANKS_N_ATMS_NAME, SCHOOLS_NAME, SPORTS_NAME,
PRINT_NAME, GATES_NAME, OTHERS_NAME };
return groupNames;
}
public static int getGroupId(String groupName) {
int result = 0;
if (groupName.equals(DEPARTMENTS_NAME))
result = DEPARTMENTS;
if (groupName.equals(HOSTELS_NAME))
result = HOSTELS;
if (groupName.equals(RESIDENCES_NAME))
result = RESIDENCES;
if (groupName.equals(HALLS_N_AUDITORIUMS_NAME))
result = HALLS_N_AUDITORIUMS;
if (groupName.equals(FOOD_STALLS_NAME))
result = FOOD_STALLS;
if (groupName.equals(BANKS_N_ATMS_NAME))
result = BANKS_N_ATMS;
if (groupName.equals(SCHOOLS_NAME))
result = SCHOOLS;
if (groupName.equals(SPORTS_NAME))
result = SPORTS;
if (groupName.equals(OTHERS_NAME))
result = OTHERS;
if (groupName.equals(GATES_NAME))
result = GATES;
if (groupName.equals(PRINT_NAME))
result = PRINT;
if (groupName.equals(LABS_NAME))
result = LABS;
return result;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getShortName() {
return shortName;
}
public void setShortName(String shortName) {
this.shortName = shortName;
}
public PointF getPoint() {
return point;
}
public void setPoint(PointF point) {
this.point = point;
}
public int getGroupIndex() {
return groupIndex;
}
public void setGroupIndex(int groupIndex) {
this.groupIndex = groupIndex;
}
public boolean isShowDefault() {
return showDefault;
}
public void setShowDefault(boolean showDefault) {
this.showDefault = showDefault;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
public String getImageUri() {
return imageUri;
}
public void setImageUri(String imageUri) {
this.imageUri = imageUri;
}
public int[] getChildIds() {
return childIds;
}
public void setChildIds(int[] childIds) {
this.childIds = childIds;
}
public int getParentId() {
return parentId;
}
public void setParentId(int parentId) {
this.parentId = parentId;
}
public String getParentRel() {
return parentRel;
}
public void setParentRel(String parentRel) {
this.parentRel = parentRel;
}
public long getLat() {
return lat;
}
public void setLat(long lat) {
this.lat = lat;
}
public long getLng() {
return lng;
}
public void setLng(long lng) {
this.lng = lng;
}
}
package com.mrane.data;
public class Room extends Marker {
public String parentKey;
public String tag;
public Room(String fullName, String shortName, float x, float y,
int groupId, String parentName, String tag, String desc) {
super(fullName, shortName, x, y, groupId, desc);
this.tag = tag;
this.parentKey = parentName;
}
}
package com.mrane.navigation;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.os.Build;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Interpolator;
import app.insti.R;
import app.insti.fragment.MapFragment;
import com.mrane.navigation.SlidingUpPanelLayout.PanelSlideListener;
public class CardSlideListener implements PanelSlideListener,
ValueAnimator.AnimatorUpdateListener {
private MapFragment mainActivity;
private SlidingUpPanelLayout slidingLayout;
private EndDetectScrollView scrollView;
private ValueAnimator animator;
private static final long TIME_ANIMATION_SHOW = 250;
public CardSlideListener(MapFragment mainActivity) {
this.mainActivity = mainActivity;
slidingLayout = mainActivity.getSlidingLayout();
scrollView = (EndDetectScrollView) mainActivity.getActivity()
.findViewById(R.id.new_expanded_place_card_scroll);
animator = new ValueAnimator();
animator.addUpdateListener(this);
Interpolator i = new Interpolator() {
public float getInterpolation(float t) {
t -= 1.0f;
return t * t * t * t * t + 1.0f;
}
};
animator.setInterpolator(i);
}
@Override
public void onPanelSlide(View panel, float slideOffset) {
// setActionBarTranslation(slidingLayout.getCurrentParalaxOffset());
// if(slideOffset >= slidingLayout.getAnchorPoint()){
// mainActivity.getSupportActionBar().hide();
// }
// else{
// mainActivity.getSupportActionBar().show();
// }
}
@Override
public void onPanelCollapsed(View panel) {
}
@Override
public void onPanelExpanded(View panel) {
scrollView.requestDisallowInterceptTouchEvent(false);
scrollView.setScrollingEnabled(true);
}
@Override
public void onPanelAnchored(View panel) {
scrollView.requestDisallowInterceptTouchEvent(true);
scrollView.setScrollingEnabled(false);
}
@Override
public void onPanelHidden(View panel) {
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void setActionBarTranslation(float y) {
// Figure out the actionbar height
int actionBarHeight = 20;
// A hack to add the translation to the action bar
ViewGroup content = ((ViewGroup) mainActivity.getActivity().findViewById(
android.R.id.content).getParent());
int children = content.getChildCount();
for (int i = 0; i < children; i++) {
View child = content.getChildAt(i);
if (child.getId() != android.R.id.content) {
if (y <= -actionBarHeight) {
child.setVisibility(View.GONE);
} else {
child.setVisibility(View.VISIBLE);
child.setTranslationY(y);
}
}
}
}
public void dismissCard() {
animator.cancel();
int initialPanelHeight = slidingLayout.getPanelHeight();
int finalPanelHeight = 0;
animator.setIntValues(initialPanelHeight, finalPanelHeight);
animator.setDuration(TIME_ANIMATION_SHOW);
animator.start();
}
public void showCard() {
animator.cancel();
int initialPanelHeight = slidingLayout.getPanelHeight();
int finalPanelHeight = mainActivity.getResources()
.getDimensionPixelSize(R.dimen.hidden_card_height);
animator.setIntValues(initialPanelHeight, finalPanelHeight);
animator.setDuration(TIME_ANIMATION_SHOW);
animator.start();
}
@Override
public void onAnimationUpdate(ValueAnimator animator) {
int panelHeight = (Integer) animator.getAnimatedValue();
slidingLayout.setPanelHeight(panelHeight);
}
}
package com.mrane.navigation;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ScrollView;
public class EndDetectScrollView extends ScrollView {
private enum ScrollState {
TOP, BETWEEN, BOTTOM
}
private ScrollState mCurrState = ScrollState.TOP;
private boolean scrollable = true;
public interface ScrollEndListener {
public void onScrollHitBottom();
public void onScrollHitTop();
public void onScrollInBetween();
}
private ScrollEndListener listener;
public EndDetectScrollView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public EndDetectScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public EndDetectScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public void setScrollEndListener(ScrollEndListener l) {
listener = l;
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
View bottomChild = (View) getChildAt(getChildCount() - 1);
int bottomDiff = (bottomChild.getBottom() - (getHeight() + getScrollY() + bottomChild
.getTop()));// Calculate the scrolldiff
if (getScrollY() == 0) { // if scrollY==0 top has been reached
if (listener != null)
listener.onScrollHitTop();
mCurrState = ScrollState.TOP;
} else if (bottomDiff == 0) {
if (listener != null)
listener.onScrollHitBottom();
mCurrState = ScrollState.BOTTOM;
} else {
if (listener != null)
listener.onScrollInBetween();
mCurrState = ScrollState.BETWEEN;
}
super.onScrollChanged(l, t, oldl, oldt);
}
public boolean isAtTop() {
return mCurrState == ScrollState.TOP;
}
public boolean isAtBottom() {
return mCurrState == ScrollState.BOTTOM;
}
public boolean isInBetween() {
return mCurrState == ScrollState.BETWEEN;
}
public void setScrollingEnabled(boolean scrollable) {
this.scrollable = scrollable;
}
public boolean isScrollable() {
return scrollable;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
// if we can scroll pass the event to the superclass
if (scrollable)
return super.onTouchEvent(ev);
// only continue to handle the touch event if scrolling enabled
return scrollable; // scrollable is always false at this point
default:
return super.onTouchEvent(ev);
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// Don't do anything with intercepted touch events if
// we are not scrollable
if (!scrollable)
return false;
else
return super.onInterceptTouchEvent(ev);
}
}
package com.mrane.navigation;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v4.view.MotionEventCompat;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import app.insti.R;
public class SlidingUpPanelLayout extends ViewGroup {
/**
* Default peeking out panel height
*/
private static final int DEFAULT_PANEL_HEIGHT = 68; // dp;
/**
* Default anchor point height
*/
private static final float DEFAULT_ANCHOR_POINT = 1.0f; // In relative %
/**
* Default initial state for the component
*/
private static SlideState DEFAULT_SLIDE_STATE = SlideState.COLLAPSED;
/**
* Default height of the shadow above the peeking out panel
*/
private static final int DEFAULT_SHADOW_HEIGHT = 4; // dp;
/**
* If no fade color is given by default it will fade to 80% gray.
*/
private static final int DEFAULT_FADE_COLOR = 0x99000000;
/**
* Default Minimum velocity that will be detected as a fling
*/
private static final int DEFAULT_MIN_FLING_VELOCITY = 400; // dips per second
/**
* Default is set to false because that is how it was written
*/
private static final boolean DEFAULT_OVERLAY_FLAG = false;
/**
* Default attributes for layout
*/
private static final int[] DEFAULT_ATTRS = new int[] {
android.R.attr.gravity
};
/**
* Minimum velocity that will be detected as a fling
*/
private int mMinFlingVelocity = DEFAULT_MIN_FLING_VELOCITY;
/**
* The fade color used for the panel covered by the slider. 0 = no fading.
*/
private int mCoveredFadeColor = DEFAULT_FADE_COLOR;
/**
* Default paralax length of the main view
*/
private static final int DEFAULT_PARALAX_OFFSET = 0;
/**
* The paint used to dim the main layout when sliding
*/
private final Paint mCoveredFadePaint = new Paint();
/**
* Drawable used to draw the shadow between panes.
*/
private final Drawable mShadowDrawable;
/**
* The size of the overhang in pixels.
*/
private int mPanelHeight = -1;
/**
* The size of the shadow in pixels.
*/
private int mShadowHeight = -1;
/**
* Paralax offset
*/
private int mParallaxOffset = -1;
/**
* True if the collapsed panel should be dragged up.
*/
private boolean mIsSlidingUp;
/**
* Panel overlays the windows instead of putting it underneath it.
*/
private boolean mOverlayContent = DEFAULT_OVERLAY_FLAG;
/**
* If provided, the panel can be dragged by only this view. Otherwise, the entire panel can be
* used for dragging.
*/
private View mDragView;
/**
* If provided, the panel can be dragged by only this view. Otherwise, the entire panel can be
* used for dragging.
*/
private int mDragViewResId = -1;
/**
* The child view that can slide, if any.
*/
private View mSlideableView;
/**
* The main view
*/
private View mMainView;
/**
* Current state of the slideable view.
*/
private enum SlideState {
EXPANDED,
COLLAPSED,
ANCHORED,
HIDDEN,
DRAGGING
}
private SlideState mSlideState = SlideState.COLLAPSED;
/**
* How far the panel is offset from its expanded position.
* range [0, 1] where 0 = collapsed, 1 = expanded.
*/
private float mSlideOffset;
/**
* How far in pixels the slideable panel may move.
*/
private int mSlideRange;
/**
* A panel view is locked into internal scrolling or another condition that
* is preventing a drag.
*/
private boolean mIsUnableToDrag;
/**
* Flag indicating that sliding feature is enabled\disabled
*/
private boolean mIsSlidingEnabled;
/**
* Flag indicating if a drag view can have its own touch events. If set
* to true, a drag view can scroll horizontally and have its own click listener.
*
* Default is set to false.
*/
private boolean mIsUsingDragViewTouchEvents;
private float mInitialMotionX;
private float mInitialMotionY;
private float mAnchorPoint = 1.f;
private PanelSlideListener mPanelSlideListener;
private final ViewDragHelper mDragHelper;
/**
* Stores whether or not the pane was expanded the last time it was slideable.
* If expand/collapse operations are invoked this state is modified. Used by
* instance state save/restore.
*/
private boolean mFirstLayout = true;
private final Rect mTmpRect = new Rect();
/**
* Listener for monitoring events about sliding panes.
*/
public interface PanelSlideListener {
/**
* Called when a sliding pane's position changes.
* @param panel The child view that was moved
* @param slideOffset The new offset of this sliding pane within its range, from 0-1
*/
public void onPanelSlide(View panel, float slideOffset);
/**
* Called when a sliding panel becomes slid completely collapsed.
* @param panel The child view that was slid to an collapsed position
*/
public void onPanelCollapsed(View panel);
/**
* Called when a sliding panel becomes slid completely expanded.
* @param panel The child view that was slid to a expanded position
*/
public void onPanelExpanded(View panel);
/**
* Called when a sliding panel becomes anchored.
* @param panel The child view that was slid to a anchored position
*/
public void onPanelAnchored(View panel);
/**
* Called when a sliding panel becomes completely hidden.
* @param panel The child view that was slid to a hidden position
*/
public void onPanelHidden(View panel);
}
public SlidingUpPanelLayout(Context context) {
this(context, null);
}
public SlidingUpPanelLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SlidingUpPanelLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
if(isInEditMode()) {
mShadowDrawable = null;
mDragHelper = null;
return;
}
if (attrs != null) {
TypedArray defAttrs = context.obtainStyledAttributes(attrs, DEFAULT_ATTRS);
if (defAttrs != null) {
int gravity = defAttrs.getInt(0, Gravity.NO_GRAVITY);
if (gravity != Gravity.TOP && gravity != Gravity.BOTTOM) {
throw new IllegalArgumentException("gravity must be set to either top or bottom");
}
mIsSlidingUp = gravity == Gravity.BOTTOM;
}
defAttrs.recycle();
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingUpPanelLayout);
if (ta != null) {
mPanelHeight = ta.getDimensionPixelSize(R.styleable.SlidingUpPanelLayout_panelHeight, -1);
mShadowHeight = ta.getDimensionPixelSize(R.styleable.SlidingUpPanelLayout_shadowHeight, -1);
mParallaxOffset = ta.getDimensionPixelSize(R.styleable.SlidingUpPanelLayout_paralaxOffset, -1);
mMinFlingVelocity = ta.getInt(R.styleable.SlidingUpPanelLayout_flingVelocity, DEFAULT_MIN_FLING_VELOCITY);
mCoveredFadeColor = ta.getColor(R.styleable.SlidingUpPanelLayout_fadeColor, DEFAULT_FADE_COLOR);
mDragViewResId = ta.getResourceId(R.styleable.SlidingUpPanelLayout_dragView, -1);
mOverlayContent = ta.getBoolean(R.styleable.SlidingUpPanelLayout_overlay,DEFAULT_OVERLAY_FLAG);
mAnchorPoint = ta.getFloat(R.styleable.SlidingUpPanelLayout_anchorPoint, DEFAULT_ANCHOR_POINT);
mSlideState = SlideState.values()[ta.getInt(R.styleable.SlidingUpPanelLayout_initialState, DEFAULT_SLIDE_STATE.ordinal())];
}
ta.recycle();
}
final float density = context.getResources().getDisplayMetrics().density;
if (mPanelHeight == -1) {
mPanelHeight = (int) (DEFAULT_PANEL_HEIGHT * density + 0.5f);
}
if (mShadowHeight == -1) {
mShadowHeight = (int) (DEFAULT_SHADOW_HEIGHT * density + 0.5f);
}
if (mParallaxOffset == -1) {
mParallaxOffset = (int) (DEFAULT_PARALAX_OFFSET * density);
}
// If the shadow height is zero, don't show the shadow
if (mShadowHeight > 0) {
if (mIsSlidingUp) {
mShadowDrawable = getResources().getDrawable(R.drawable.above_shadow);
} else {
mShadowDrawable = getResources().getDrawable(R.drawable.below_shadow);
}
} else {
mShadowDrawable = null;
}
setWillNotDraw(false);
mDragHelper = ViewDragHelper.create(this, 0.5f, new DragHelperCallback());
mDragHelper.setMinVelocity(mMinFlingVelocity * density);
mIsSlidingEnabled = true;
}
/**
* Set the Drag View after the view is inflated
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate();
if (mDragViewResId != -1) {
setDragView(findViewById(mDragViewResId));
}
}
public boolean isSlidingEnabled() {
return mIsSlidingEnabled && mSlideableView != null;
}
/**
* Set the collapsed panel height in pixels
*
* @param val A height in pixels
*/
public void setPanelHeight(int val) {
mPanelHeight = val;
int newTop = computePanelTopPosition(0.0f);
mSlideOffset = computeSlideOffset(newTop);
onPanelDragged(newTop);
}
/**
* @return The current collapsed panel height
*/
public int getPanelHeight() {
return mPanelHeight;
}
/**
* @return The current paralax offset
*/
public int getCurrentParalaxOffset() {
// Clamp slide offset at zero for parallax computation;
int offset = (int)(mParallaxOffset * Math.max(mSlideOffset, 0));
return mIsSlidingUp ? -offset : offset;
}
/**
* Sets the panel slide listener
* @param listener
*/
public void setPanelSlideListener(PanelSlideListener listener) {
mPanelSlideListener = listener;
}
/**
* Set the draggable view portion. Use to null, to allow the whole panel to be draggable
*
* @param dragView A view that will be used to drag the panel.
*/
public void setDragView(View dragView) {
if (mDragView != null) {
mDragView.setOnClickListener(null);
}
mDragView = dragView;
if (mDragView != null) {
mDragView.setClickable(true);
mDragView.setFocusable(false);
mDragView.setFocusableInTouchMode(false);
mDragView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (!isEnabled()) return;
if (!isPanelExpanded() && !isPanelAnchored()) {
expandPanel(mAnchorPoint);
} else {
collapsePanel();
}
}
});;
}
}
/**
* Set an anchor point where the panel can stop during sliding
*
* @param anchorPoint A value between 0 and 1, determining the position of the anchor point
* starting from the top of the layout.
*/
public void setAnchorPoint(float anchorPoint) {
if (anchorPoint > 0 && anchorPoint <= 1) {
mAnchorPoint = anchorPoint;
}
}
void dispatchOnPanelSlide(View panel) {
if (mPanelSlideListener != null) {
mPanelSlideListener.onPanelSlide(panel, mSlideOffset);
}
}
void dispatchOnPanelExpanded(View panel) {
if (mPanelSlideListener != null) {
mPanelSlideListener.onPanelExpanded(panel);
}
sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
}
void dispatchOnPanelCollapsed(View panel) {
if (mPanelSlideListener != null) {
mPanelSlideListener.onPanelCollapsed(panel);
}
sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
}
void dispatchOnPanelAnchored(View panel) {
if (mPanelSlideListener != null) {
mPanelSlideListener.onPanelAnchored(panel);
}
sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
}
void dispatchOnPanelHidden(View panel) {
if (mPanelSlideListener != null) {
mPanelSlideListener.onPanelHidden(panel);
}
sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
}
void updateObscuredViewVisibility() {
if (getChildCount() == 0) {
return;
}
final int leftBound = getPaddingLeft();
final int rightBound = getWidth() - getPaddingRight();
final int topBound = getPaddingTop();
final int bottomBound = getHeight() - getPaddingBottom();
final int left;
final int right;
final int top;
final int bottom;
if (mSlideableView != null && hasOpaqueBackground(mSlideableView)) {
left = mSlideableView.getLeft();
right = mSlideableView.getRight();
top = mSlideableView.getTop();
bottom = mSlideableView.getBottom();
} else {
left = right = top = bottom = 0;
}
View child = getChildAt(0);
final int clampedChildLeft = Math.max(leftBound, child.getLeft());
final int clampedChildTop = Math.max(topBound, child.getTop());
final int clampedChildRight = Math.min(rightBound, child.getRight());
final int clampedChildBottom = Math.min(bottomBound, child.getBottom());
final int vis;
if (clampedChildLeft >= left && clampedChildTop >= top &&
clampedChildRight <= right && clampedChildBottom <= bottom) {
vis = INVISIBLE;
} else {
vis = VISIBLE;
}
child.setVisibility(vis);
}
void setAllChildrenVisible() {
for (int i = 0, childCount = getChildCount(); i < childCount; i++) {
final View child = getChildAt(i);
if (child.getVisibility() == INVISIBLE) {
child.setVisibility(VISIBLE);
}
}
}
private static boolean hasOpaqueBackground(View v) {
final Drawable bg = v.getBackground();
return bg != null && bg.getOpacity() == PixelFormat.OPAQUE;
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mFirstLayout = true;
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mFirstLayout = true;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
if (widthMode != MeasureSpec.EXACTLY) {
throw new IllegalStateException("Width must have an exact value or MATCH_PARENT");
} else if (heightMode != MeasureSpec.EXACTLY) {
throw new IllegalStateException("Height must have an exact value or MATCH_PARENT");
}
final int childCount = getChildCount();
if (childCount != 2) {
throw new IllegalStateException("Sliding up panel layout must have exactly 2 children!");
}
mMainView = getChildAt(0);
mSlideableView = getChildAt(1);
if (mDragView == null) {
setDragView(mSlideableView);
}
// If the sliding panel is not visible, then put the whole view in the hidden state
if (mSlideableView.getVisibility() == GONE) {
mSlideState = SlideState.HIDDEN;
}
int layoutHeight = heightSize - getPaddingTop() - getPaddingBottom();
// First pass. Measure based on child LayoutParams width/height.
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
// We always measure the sliding panel in order to know it's height (needed for show panel)
if (child.getVisibility() == GONE && i == 0) {
continue;
}
int height = layoutHeight;
if (child == mMainView && !mOverlayContent && mSlideState != SlideState.HIDDEN) {
height -= mPanelHeight;
}
int childWidthSpec;
if (lp.width == LayoutParams.WRAP_CONTENT) {
childWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.AT_MOST);
} else if (lp.width == LayoutParams.MATCH_PARENT) {
childWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY);
} else {
childWidthSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
}
int childHeightSpec;
if (lp.height == LayoutParams.WRAP_CONTENT) {
childHeightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
} else if (lp.height == LayoutParams.MATCH_PARENT) {
childHeightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
} else {
childHeightSpec = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY);
}
if (child == mSlideableView) {
mSlideRange = MeasureSpec.getSize(childHeightSpec) - mPanelHeight;
}
child.measure(childWidthSpec, childHeightSpec);
}
setMeasuredDimension(widthSize, heightSize);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int paddingLeft = getPaddingLeft();
final int paddingTop = getPaddingTop();
final int childCount = getChildCount();
if (mFirstLayout) {
switch (mSlideState) {
case EXPANDED:
mSlideOffset = 1.0f;
break;
case ANCHORED:
mSlideOffset = mAnchorPoint;
break;
case HIDDEN:
int newTop = computePanelTopPosition(0.0f) + (mIsSlidingUp ? +mPanelHeight : -mPanelHeight);
mSlideOffset = computeSlideOffset(newTop);
break;
default:
mSlideOffset = 0.f;
break;
}
}
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
// Always layout the sliding view on the first layout
if (child.getVisibility() == GONE && (i == 0 || mFirstLayout)) {
continue;
}
final int childHeight = child.getMeasuredHeight();
int childTop = paddingTop;
if (child == mSlideableView) {
childTop = computePanelTopPosition(mSlideOffset);
}
if (!mIsSlidingUp) {
if (child == mMainView && !mOverlayContent) {
childTop = computePanelTopPosition(mSlideOffset) + mSlideableView.getMeasuredHeight();
}
}
final int childBottom = childTop + childHeight;
final int childLeft = paddingLeft;
final int childRight = childLeft + child.getMeasuredWidth();
child.layout(childLeft, childTop, childRight, childBottom);
}
if (mFirstLayout) {
updateObscuredViewVisibility();
}
mFirstLayout = false;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// Recalculate sliding panes and their details
if (h != oldh) {
mFirstLayout = true;
}
}
@Override
public void setEnabled(boolean enabled) {
if (!enabled) {
collapsePanel();
}
super.setEnabled(enabled);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
final int action = MotionEventCompat.getActionMasked(ev);
if (!isEnabled() || !mIsSlidingEnabled || (mIsUnableToDrag && action != MotionEvent.ACTION_DOWN)) {
mDragHelper.cancel();
return super.onInterceptTouchEvent(ev);
}
if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
mDragHelper.cancel();
return false;
}
final float x = ev.getX();
final float y = ev.getY();
switch (action) {
case MotionEvent.ACTION_DOWN: {
mIsUnableToDrag = false;
mInitialMotionX = x;
mInitialMotionY = y;
break;
}
case MotionEvent.ACTION_MOVE: {
final float adx = Math.abs(x - mInitialMotionX);
final float ady = Math.abs(y - mInitialMotionY);
final int dragSlop = mDragHelper.getTouchSlop();
// Handle any horizontal scrolling on the drag view.
if (mIsUsingDragViewTouchEvents && adx > dragSlop && ady < dragSlop) {
return super.onInterceptTouchEvent(ev);
}
if ((ady > dragSlop && adx > ady) || !isDragViewUnder((int)mInitialMotionX, (int)mInitialMotionY)) {
mDragHelper.cancel();
mIsUnableToDrag = true;
return false;
}
break;
}
}
return mDragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (!isSlidingEnabled()) {
return super.onTouchEvent(ev);
}
mDragHelper.processTouchEvent(ev);
return true;
}
private boolean isDragViewUnder(int x, int y) {
if (mDragView == null) return false;
int[] viewLocation = new int[2];
mDragView.getLocationOnScreen(viewLocation);
int[] parentLocation = new int[2];
this.getLocationOnScreen(parentLocation);
int screenX = parentLocation[0] + x;
int screenY = parentLocation[1] + y;
return screenX >= viewLocation[0] && screenX < viewLocation[0] + mDragView.getWidth() &&
screenY >= viewLocation[1] && screenY < viewLocation[1] + mDragView.getHeight();
}
private boolean expandPanel(View pane, int initialVelocity, float mSlideOffset) {
return mFirstLayout || smoothSlideTo(mSlideOffset, initialVelocity);
}
private boolean collapsePanel(View pane, int initialVelocity) {
return mFirstLayout || smoothSlideTo(0.0f, initialVelocity);
}
/*
* Computes the top position of the panel based on the slide offset.
*/
private int computePanelTopPosition(float slideOffset) {
int slidingViewHeight = mSlideableView != null ? mSlideableView.getMeasuredHeight() : 0;
int slidePixelOffset = (int) (slideOffset * mSlideRange);
// Compute the top of the panel if its collapsed
return mIsSlidingUp
? getMeasuredHeight() - getPaddingBottom() - mPanelHeight - slidePixelOffset
: getPaddingTop() - slidingViewHeight + mPanelHeight + slidePixelOffset;
}
/*
* Computes the slide offset based on the top position of the panel
*/
private float computeSlideOffset(int topPosition) {
// Compute the panel top position if the panel is collapsed (offset 0)
final int topBoundCollapsed = computePanelTopPosition(0);
// Determine the new slide offset based on the collapsed top position and the new required
// top position
return (mIsSlidingUp
? (float) (topBoundCollapsed - topPosition) / mSlideRange
: (float) (topPosition - topBoundCollapsed) / mSlideRange);
}
/**
* Collapse the sliding pane if it is currently slideable. If first layout
* has already completed this will animate.
*
* @return true if the pane was slideable and is now collapsed/in the process of collapsing
*/
public boolean collapsePanel() {
if (mFirstLayout) {
mSlideState = SlideState.COLLAPSED;
return true;
} else {
if (mSlideState == SlideState.HIDDEN || mSlideState == SlideState.COLLAPSED)
return false;
return collapsePanel(mSlideableView, 0);
}
}
/**
* Partially expand the sliding panel up to a specific offset
*
* @param mSlideOffset Value between 0 and 1, where 0 is completely expanded.
* @return true if the pane was slideable and is now expanded/in the process of expanding
*/
public boolean expandPanel(float mSlideOffset) {
if (mSlideableView == null || mSlideState == SlideState.EXPANDED) return false;
mSlideableView.setVisibility(View.VISIBLE);
return expandPanel(mSlideableView, 0, mSlideOffset);
}
/**
* Check if the sliding panel in this layout is fully expanded.
*
* @return true if sliding panel is completely expanded
*/
public boolean isPanelExpanded() {
return mSlideState == SlideState.EXPANDED;
}
/**
* Check if the sliding panel in this layout is anchored.
*
* @return true if sliding panel is anchored
*/
public boolean isPanelAnchored() {
return mSlideState == SlideState.ANCHORED;
}
@SuppressLint("NewApi")
private void onPanelDragged(int newTop) {
mSlideState = SlideState.DRAGGING;
// Recompute the slide offset based on the new top position
mSlideOffset = computeSlideOffset(newTop);
// Update the parallax based on the new slide offset
if (mParallaxOffset > 0 && mSlideOffset >= 0) {
int mainViewOffset = getCurrentParalaxOffset();
mMainView.setTranslationY(mainViewOffset);
}
// Dispatch the slide event
dispatchOnPanelSlide(mSlideableView);
// If the slide offset is negative, and overlay is not on, we need to increase the
// height of the main content
if (mSlideOffset <= 0 && !mOverlayContent) {
// expand the main view
LayoutParams lp = (LayoutParams)mMainView.getLayoutParams();
lp.height = mIsSlidingUp ? (newTop - getPaddingBottom()) : (getHeight() - getPaddingBottom() - mSlideableView.getMeasuredHeight() - newTop);
mMainView.requestLayout();
}
}
@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
boolean result;
final int save = canvas.save(Canvas.CLIP_SAVE_FLAG);
if (isSlidingEnabled() && mSlideableView != child) {
// Clip against the slider; no sense drawing what will immediately be covered,
// Unless the panel is set to overlay content
if (!mOverlayContent) {
canvas.getClipBounds(mTmpRect);
if (mIsSlidingUp) {
mTmpRect.bottom = Math.min(mTmpRect.bottom, mSlideableView.getTop());
} else {
mTmpRect.top = Math.max(mTmpRect.top, mSlideableView.getBottom());
}
canvas.clipRect(mTmpRect);
}
}
result = super.drawChild(canvas, child, drawingTime);
canvas.restoreToCount(save);
if (mCoveredFadeColor != 0 && mSlideOffset > 0) {
final int baseAlpha = (mCoveredFadeColor & 0xff000000) >>> 24;
final int imag = (int) (baseAlpha * mSlideOffset);
final int color = imag << 24 | (mCoveredFadeColor & 0xffffff);
mCoveredFadePaint.setColor(color);
canvas.drawRect(mTmpRect, mCoveredFadePaint);
}
return result;
}
/**
* Smoothly animate mDraggingPane to the target X position within its range.
*
* @param slideOffset position to animate to
* @param velocity initial velocity in case of fling, or 0.
*/
boolean smoothSlideTo(float slideOffset, int velocity) {
if (!isSlidingEnabled()) {
// Nothing to do.
return false;
}
int panelTop = computePanelTopPosition(slideOffset);
if (mDragHelper.smoothSlideViewTo(mSlideableView, mSlideableView.getLeft(), panelTop)) {
setAllChildrenVisible();
ViewCompat.postInvalidateOnAnimation(this);
return true;
}
return false;
}
@Override
public void computeScroll() {
if (mDragHelper != null && mDragHelper.continueSettling(true)) {
if (!isSlidingEnabled()) {
mDragHelper.abort();
return;
}
ViewCompat.postInvalidateOnAnimation(this);
}
}
@Override
public void draw(Canvas c) {
super.draw(c);
if (!isSlidingEnabled()) {
// No need to draw a shadow if we don't have one.
return;
}
final int right = mSlideableView.getRight();
final int top;
final int bottom;
if (mIsSlidingUp) {
top = mSlideableView.getTop() - mShadowHeight;
bottom = mSlideableView.getTop();
} else {
top = mSlideableView.getBottom();
bottom = mSlideableView.getBottom() + mShadowHeight;
}
final int left = mSlideableView.getLeft();
if (mShadowDrawable != null) {
mShadowDrawable.setBounds(left, top, right, bottom);
mShadowDrawable.draw(c);
}
}
@Override
protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
return new LayoutParams();
}
@Override
protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
return p instanceof MarginLayoutParams
? new LayoutParams((MarginLayoutParams) p)
: new LayoutParams(p);
}
@Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p instanceof LayoutParams && super.checkLayoutParams(p);
}
@Override
public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
return new LayoutParams(getContext(), attrs);
}
@Override
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
ss.mSlideState = mSlideState;
return ss;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
mSlideState = ss.mSlideState;
}
private class DragHelperCallback extends ViewDragHelper.Callback {
@Override
public boolean tryCaptureView(View child, int pointerId) {
if (mIsUnableToDrag) {
return false;
}
return child == mSlideableView;
}
@Override
public void onViewDragStateChanged(int state) {
if (mDragHelper.getViewDragState() == ViewDragHelper.STATE_IDLE) {
mSlideOffset = computeSlideOffset(mSlideableView.getTop());
if (mSlideOffset == 1) {
if (mSlideState != SlideState.EXPANDED) {
updateObscuredViewVisibility();
mSlideState = SlideState.EXPANDED;
dispatchOnPanelExpanded(mSlideableView);
}
} else if (mSlideOffset == 0) {
if (mSlideState != SlideState.COLLAPSED) {
mSlideState = SlideState.COLLAPSED;
dispatchOnPanelCollapsed(mSlideableView);
}
} else if (mSlideOffset < 0) {
mSlideState = SlideState.HIDDEN;
mSlideableView.setVisibility(View.GONE);
dispatchOnPanelHidden(mSlideableView);
} else if (mSlideState != SlideState.ANCHORED) {
updateObscuredViewVisibility();
mSlideState = SlideState.ANCHORED;
dispatchOnPanelAnchored(mSlideableView);
}
}
}
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
setAllChildrenVisible();
}
@Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
onPanelDragged(top);
invalidate();
}
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
int target = 0;
// direction is always positive if we are sliding in the expanded direction
float direction = mIsSlidingUp ? -yvel : yvel;
if (direction > 0) {
// swipe up -> expand
target = computePanelTopPosition(1.0f);
} else if (direction < 0) {
// swipe down -> collapse
target = computePanelTopPosition(0.0f);
} else if (mAnchorPoint != 1 && mSlideOffset >= (1.f + mAnchorPoint) / 2) {
// zero velocity, and far enough from anchor point => expand to the top
target = computePanelTopPosition(1.0f);
} else if (mAnchorPoint == 1 && mSlideOffset >= 0.5f) {
// zero velocity, and far enough from anchor point => expand to the top
target = computePanelTopPosition(1.0f);
} else if (mAnchorPoint != 1 && mSlideOffset >= mAnchorPoint) {
target = computePanelTopPosition(mAnchorPoint);
} else if (mAnchorPoint != 1 && mSlideOffset >= mAnchorPoint / 2) {
target = computePanelTopPosition(mAnchorPoint);
} else {
// settle at the bottom
target = computePanelTopPosition(0.0f);
}
mDragHelper.settleCapturedViewAt(releasedChild.getLeft(), target);
invalidate();
}
@Override
public int getViewVerticalDragRange(View child) {
return mSlideRange;
}
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
final int collapsedTop = computePanelTopPosition(0.f);
final int expandedTop = computePanelTopPosition(1.0f);
if (mIsSlidingUp) {
return Math.min(Math.max(top, expandedTop), collapsedTop);
} else {
return Math.min(Math.max(top, collapsedTop), expandedTop);
}
}
}
public static class LayoutParams extends ViewGroup.MarginLayoutParams {
private static final int[] ATTRS = new int[] {
android.R.attr.layout_weight
};
public LayoutParams() {
super(MATCH_PARENT, MATCH_PARENT);
}
public LayoutParams(android.view.ViewGroup.LayoutParams source) {
super(source);
}
public LayoutParams(MarginLayoutParams source) {
super(source);
}
public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
final TypedArray a = c.obtainStyledAttributes(attrs, ATTRS);
a.recycle();
}
}
static class SavedState extends BaseSavedState {
SlideState mSlideState;
SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
try {
mSlideState = Enum.valueOf(SlideState.class, in.readString());
} catch (IllegalArgumentException e) {
mSlideState = SlideState.COLLAPSED;
}
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeString(mSlideState.toString());
}
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];
}
};
}
}
/*
* Copyright (C) 2013 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 com.mrane.navigation;
import android.content.Context;
import android.support.v4.view.MotionEventCompat;
import android.support.v4.view.VelocityTrackerCompat;
import android.support.v4.widget.ScrollerCompat;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.animation.Interpolator;
import java.util.Arrays;
/**
* ViewDragHelper is a utility class for writing custom ViewGroups. It offers a number
* of useful operations and state tracking for allowing a user to drag and reposition
* views within their parent ViewGroup.
*/
public class ViewDragHelper {
/**
* A null/invalid pointer ID.
*/
public static final int INVALID_POINTER = -1;
/**
* A view is not currently being dragged or animating as a result of a fling/snap.
*/
public static final int STATE_IDLE = 0;
/**
* A view is currently being dragged. The position is currently changing as a result
* of user input or simulated user input.
*/
public static final int STATE_DRAGGING = 1;
/**
* A view is currently settling into place as a result of a fling or
* predefined non-interactive motion.
*/
public static final int STATE_SETTLING = 2;
/**
* Edge flag indicating that the left edge should be affected.
*/
public static final int EDGE_LEFT = 1 << 0;
/**
* Edge flag indicating that the right edge should be affected.
*/
public static final int EDGE_RIGHT = 1 << 1;
/**
* Edge flag indicating that the top edge should be affected.
*/
public static final int EDGE_TOP = 1 << 2;
/**
* Edge flag indicating that the bottom edge should be affected.
*/
public static final int EDGE_BOTTOM = 1 << 3;
/**
* Indicates that a check should occur along the horizontal axis
*/
public static final int DIRECTION_HORIZONTAL = 1 << 0;
/**
* Indicates that a check should occur along the vertical axis
*/
public static final int DIRECTION_VERTICAL = 1 << 1;
private static final int EDGE_SIZE = 20; // dp
private static final int BASE_SETTLE_DURATION = 256; // ms
private static final int MAX_SETTLE_DURATION = 600; // ms
// Current drag state; idle, dragging or settling
private int mDragState;
// Distance to travel before a drag may begin
private int mTouchSlop;
// Last known position/pointer tracking
private int mActivePointerId = INVALID_POINTER;
private float[] mInitialMotionX;
private float[] mInitialMotionY;
private float[] mLastMotionX;
private float[] mLastMotionY;
private int[] mInitialEdgesTouched;
private int[] mEdgeDragsInProgress;
private int[] mEdgeDragsLocked;
private int mPointersDown;
private VelocityTracker mVelocityTracker;
private float mMaxVelocity;
private float mMinVelocity;
private int mEdgeSize;
private int mTrackingEdges;
private ScrollerCompat mScroller;
private final Callback mCallback;
private View mCapturedView;
private boolean mReleaseInProgress;
private final ViewGroup mParentView;
/**
* A Callback is used as a communication channel with the ViewDragHelper back to the
* parent view using it. <code>on*</code>methods are invoked on siginficant events and several
* accessor methods are expected to provide the ViewDragHelper with more information
* about the state of the parent view upon request. The callback also makes decisions
* governing the range and draggability of child views.
*/
public static abstract class Callback {
/**
* Called when the drag state changes. See the <code>STATE_*</code> constants
* for more information.
*
* @param state The new drag state
*
* @see #STATE_IDLE
* @see #STATE_DRAGGING
* @see #STATE_SETTLING
*/
public void onViewDragStateChanged(int state) {}
/**
* Called when the captured view's position changes as the result of a drag or settle.
*
* @param changedView View whose position changed
* @param left New X coordinate of the left edge of the view
* @param top New Y coordinate of the top edge of the view
* @param dx Change in X position from the last call
* @param dy Change in Y position from the last call
*/
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {}
/**
* Called when a child view is captured for dragging or settling. The ID of the pointer
* currently dragging the captured view is supplied. If activePointerId is
* identified as {@link #INVALID_POINTER} the capture is programmatic instead of
* pointer-initiated.
*
* @param capturedChild Child view that was captured
* @param activePointerId Pointer id tracking the child capture
*/
public void onViewCaptured(View capturedChild, int activePointerId) {}
/**
* Called when the child view is no longer being actively dragged.
* The fling velocity is also supplied, if relevant. The velocity values may
* be clamped to system minimums or maximums.
*
* <p>Calling code may decide to fling or otherwise release the view to let it
* settle into place. It should do so using {@link #settleCapturedViewAt(int, int)}
* or {@link #flingCapturedView(int, int, int, int)}. If the Callback invokes
* one of these methods, the ViewDragHelper will enter {@link #STATE_SETTLING}
* and the view capture will not fully end until it comes to a complete stop.
* If neither of these methods is invoked before <code>onViewReleased</code> returns,
* the view will stop in place and the ViewDragHelper will return to
* {@link #STATE_IDLE}.</p>
*
* @param releasedChild The captured child view now being released
* @param xvel X velocity of the pointer as it left the screen in pixels per second.
* @param yvel Y velocity of the pointer as it left the screen in pixels per second.
*/
public void onViewReleased(View releasedChild, float xvel, float yvel) {}
/**
* Called when one of the subscribed edges in the parent view has been touched
* by the user while no child view is currently captured.
*
* @param edgeFlags A combination of edge flags describing the edge(s) currently touched
* @param pointerId ID of the pointer touching the described edge(s)
* @see #EDGE_LEFT
* @see #EDGE_TOP
* @see #EDGE_RIGHT
* @see #EDGE_BOTTOM
*/
public void onEdgeTouched(int edgeFlags, int pointerId) {}
/**
* Called when the given edge may become locked. This can happen if an edge drag
* was preliminarily rejected before beginning, but after {@link #onEdgeTouched(int, int)}
* was called. This method should return true to lock this edge or false to leave it
* unlocked. The default behavior is to leave edges unlocked.
*
* @param edgeFlags A combination of edge flags describing the edge(s) locked
* @return true to lock the edge, false to leave it unlocked
*/
public boolean onEdgeLock(int edgeFlags) {
return false;
}
/**
* Called when the user has started a deliberate drag away from one
* of the subscribed edges in the parent view while no child view is currently captured.
*
* @param edgeFlags A combination of edge flags describing the edge(s) dragged
* @param pointerId ID of the pointer touching the described edge(s)
* @see #EDGE_LEFT
* @see #EDGE_TOP
* @see #EDGE_RIGHT
* @see #EDGE_BOTTOM
*/
public void onEdgeDragStarted(int edgeFlags, int pointerId) {}
/**
* Called to determine the Z-order of child views.
*
* @param index the ordered position to query for
* @return index of the view that should be ordered at position <code>index</code>
*/
public int getOrderedChildIndex(int index) {
return index;
}
/**
* Return the magnitude of a draggable child view's horizontal range of motion in pixels.
* This method should return 0 for views that cannot move horizontally.
*
* @param child Child view to check
* @return range of horizontal motion in pixels
*/
public int getViewHorizontalDragRange(View child) {
return 0;
}
/**
* Return the magnitude of a draggable child view's vertical range of motion in pixels.
* This method should return 0 for views that cannot move vertically.
*
* @param child Child view to check
* @return range of vertical motion in pixels
*/
public int getViewVerticalDragRange(View child) {
return 0;
}
/**
* Called when the user's input indicates that they want to capture the given child view
* with the pointer indicated by pointerId. The callback should return true if the user
* is permitted to drag the given view with the indicated pointer.
*
* <p>ViewDragHelper may call this method multiple times for the same view even if
* the view is already captured; this indicates that a new pointer is trying to take
* control of the view.</p>
*
* <p>If this method returns true, a call to {@link #onViewCaptured(android.view.View, int)}
* will follow if the capture is successful.</p>
*
* @param child Child the user is attempting to capture
* @param pointerId ID of the pointer attempting the capture
* @return true if capture should be allowed, false otherwise
*/
public abstract boolean tryCaptureView(View child, int pointerId);
/**
* Restrict the motion of the dragged child view along the horizontal axis.
* The default implementation does not allow horizontal motion; the extending
* class must override this method and provide the desired clamping.
*
*
* @param child Child view being dragged
* @param left Attempted motion along the X axis
* @param dx Proposed change in position for left
* @return The new clamped position for left
*/
public int clampViewPositionHorizontal(View child, int left, int dx) {
return 0;
}
/**
* Restrict the motion of the dragged child view along the vertical axis.
* The default implementation does not allow vertical motion; the extending
* class must override this method and provide the desired clamping.
*
*
* @param child Child view being dragged
* @param top Attempted motion along the Y axis
* @param dy Proposed change in position for top
* @return The new clamped position for top
*/
public int clampViewPositionVertical(View child, int top, int dy) {
return 0;
}
}
/**
* Interpolator defining the animation curve for mScroller
*/
private static final Interpolator sInterpolator = new Interpolator() {
public float getInterpolation(float t) {
t -= 1.0f;
return t * t * t * t * t + 1.0f;
}
};
private final Runnable mSetIdleRunnable = new Runnable() {
public void run() {
setDragState(STATE_IDLE);
}
};
/**
* Factory method to create a new ViewDragHelper.
*
* @param forParent Parent view to monitor
* @param cb Callback to provide information and receive events
* @return a new ViewDragHelper instance
*/
public static ViewDragHelper create(ViewGroup forParent, Callback cb) {
return new ViewDragHelper(forParent.getContext(), forParent, cb);
}
/**
* Factory method to create a new ViewDragHelper.
*
* @param forParent Parent view to monitor
* @param sensitivity Multiplier for how sensitive the helper should be about detecting
* the start of a drag. Larger values are more sensitive. 1.0f is normal.
* @param cb Callback to provide information and receive events
* @return a new ViewDragHelper instance
*/
public static ViewDragHelper create(ViewGroup forParent, float sensitivity, Callback cb) {
final ViewDragHelper helper = create(forParent, cb);
helper.mTouchSlop = (int) (helper.mTouchSlop * (1 / sensitivity));
return helper;
}
/**
* Apps should use ViewDragHelper.create() to get a new instance.
* This will allow VDH to use internal compatibility implementations for different
* platform versions.
*
* @param context Context to initialize config-dependent params from
* @param forParent Parent view to monitor
*/
private ViewDragHelper(Context context, ViewGroup forParent, Callback cb) {
if (forParent == null) {
throw new IllegalArgumentException("Parent view may not be null");
}
if (cb == null) {
throw new IllegalArgumentException("Callback may not be null");
}
mParentView = forParent;
mCallback = cb;
final ViewConfiguration vc = ViewConfiguration.get(context);
final float density = context.getResources().getDisplayMetrics().density;
mEdgeSize = (int) (EDGE_SIZE * density + 0.5f);
mTouchSlop = vc.getScaledTouchSlop();
mMaxVelocity = vc.getScaledMaximumFlingVelocity();
mMinVelocity = vc.getScaledMinimumFlingVelocity();
mScroller = ScrollerCompat.create(context, sInterpolator);
}
/**
* Set the minimum velocity that will be detected as having a magnitude greater than zero
* in pixels per second. Callback methods accepting a velocity will be clamped appropriately.
*
* @param minVel Minimum velocity to detect
*/
public void setMinVelocity(float minVel) {
mMinVelocity = minVel;
}
/**
* Retrieve the current drag state of this helper. This will return one of
* {@link #STATE_IDLE}, {@link #STATE_DRAGGING} or {@link #STATE_SETTLING}.
* @return The current drag state
*/
public int getViewDragState() {
return mDragState;
}
/**
* Capture a specific child view for dragging within the parent. The callback will be notified
* but {@link Callback#tryCaptureView(android.view.View, int)} will not be asked permission to
* capture this view.
*
* @param childView Child view to capture
* @param activePointerId ID of the pointer that is dragging the captured child view
*/
public void captureChildView(View childView, int activePointerId) {
if (childView.getParent() != mParentView) {
throw new IllegalArgumentException("captureChildView: parameter must be a descendant " +
"of the ViewDragHelper's tracked parent view (" + mParentView + ")");
}
mCapturedView = childView;
mActivePointerId = activePointerId;
mCallback.onViewCaptured(childView, activePointerId);
setDragState(STATE_DRAGGING);
}
/**
* @return The minimum distance in pixels that the user must travel to initiate a drag
*/
public int getTouchSlop() {
return mTouchSlop;
}
/**
* The result of a call to this method is equivalent to
* {@link #processTouchEvent(android.view.MotionEvent)} receiving an ACTION_CANCEL event.
*/
public void cancel() {
mActivePointerId = INVALID_POINTER;
clearMotionHistory();
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
}
/**
* {@link #cancel()}, but also abort all motion in progress and snap to the end of any
* animation.
*/
public void abort() {
cancel();
if (mDragState == STATE_SETTLING) {
final int oldX = mScroller.getCurrX();
final int oldY = mScroller.getCurrY();
mScroller.abortAnimation();
final int newX = mScroller.getCurrX();
final int newY = mScroller.getCurrY();
mCallback.onViewPositionChanged(mCapturedView, newX, newY, newX - oldX, newY - oldY);
}
setDragState(STATE_IDLE);
}
/**
* Animate the view <code>child</code> to the given (left, top) position.
* If this method returns true, the caller should invoke {@link #continueSettling(boolean)}
* on each subsequent frame to continue the motion until it returns false. If this method
* returns false there is no further work to do to complete the movement.
*
* <p>This operation does not count as a capture event, though {@link #getCapturedView()}
* will still report the sliding view while the slide is in progress.</p>
*
* @param child Child view to capture and animate
* @param finalLeft Final left position of child
* @param finalTop Final top position of child
* @return true if animation should continue through {@link #continueSettling(boolean)} calls
*/
public boolean smoothSlideViewTo(View child, int finalLeft, int finalTop) {
mCapturedView = child;
mActivePointerId = INVALID_POINTER;
return forceSettleCapturedViewAt(finalLeft, finalTop, 0, 0);
}
/**
* Settle the captured view at the given (left, top) position.
* The appropriate velocity from prior motion will be taken into account.
* If this method returns true, the caller should invoke {@link #continueSettling(boolean)}
* on each subsequent frame to continue the motion until it returns false. If this method
* returns false there is no further work to do to complete the movement.
*
* @param finalLeft Settled left edge position for the captured view
* @param finalTop Settled top edge position for the captured view
* @return true if animation should continue through {@link #continueSettling(boolean)} calls
*/
public boolean settleCapturedViewAt(int finalLeft, int finalTop) {
if (!mReleaseInProgress) {
throw new IllegalStateException("Cannot settleCapturedViewAt outside of a call to " +
"Callback#onViewReleased");
}
return forceSettleCapturedViewAt(finalLeft, finalTop,
(int) VelocityTrackerCompat.getXVelocity(mVelocityTracker, mActivePointerId),
(int) VelocityTrackerCompat.getYVelocity(mVelocityTracker, mActivePointerId));
}
/**
* Settle the captured view at the given (left, top) position.
*
* @param finalLeft Target left position for the captured view
* @param finalTop Target top position for the captured view
* @param xvel Horizontal velocity
* @param yvel Vertical velocity
* @return true if animation should continue through {@link #continueSettling(boolean)} calls
*/
private boolean forceSettleCapturedViewAt(int finalLeft, int finalTop, int xvel, int yvel) {
final int startLeft = mCapturedView.getLeft();
final int startTop = mCapturedView.getTop();
final int dx = finalLeft - startLeft;
final int dy = finalTop - startTop;
if (dx == 0 && dy == 0) {
// Nothing to do. Send callbacks, be done.
mScroller.abortAnimation();
setDragState(STATE_IDLE);
return false;
}
final int duration = computeSettleDuration(mCapturedView, dx, dy, xvel, yvel);
mScroller.startScroll(startLeft, startTop, dx, dy, duration);
setDragState(STATE_SETTLING);
return true;
}
private int computeSettleDuration(View child, int dx, int dy, int xvel, int yvel) {
xvel = clampMag(xvel, (int) mMinVelocity, (int) mMaxVelocity);
yvel = clampMag(yvel, (int) mMinVelocity, (int) mMaxVelocity);
final int absDx = Math.abs(dx);
final int absDy = Math.abs(dy);
final int absXVel = Math.abs(xvel);
final int absYVel = Math.abs(yvel);
final int addedVel = absXVel + absYVel;
final int addedDistance = absDx + absDy;
final float xweight = xvel != 0 ? (float) absXVel / addedVel :
(float) absDx / addedDistance;
final float yweight = yvel != 0 ? (float) absYVel / addedVel :
(float) absDy / addedDistance;
int xduration = computeAxisDuration(dx, xvel, mCallback.getViewHorizontalDragRange(child));
int yduration = computeAxisDuration(dy, yvel, mCallback.getViewVerticalDragRange(child));
return (int) (xduration * xweight + yduration * yweight);
}
private int computeAxisDuration(int delta, int velocity, int motionRange) {
if (delta == 0) {
return 0;
}
final int width = mParentView.getWidth();
final int halfWidth = width / 2;
final float distanceRatio = Math.min(1f, (float) Math.abs(delta) / width);
final float distance = halfWidth + halfWidth *
distanceInfluenceForSnapDuration(distanceRatio);
int duration;
velocity = Math.abs(velocity);
if (velocity > 0) {
duration = 4 * Math.round(1000 * Math.abs(distance / velocity));
} else {
final float range = (float) Math.abs(delta) / motionRange;
duration = (int) ((range + 1) * BASE_SETTLE_DURATION);
}
return Math.min(duration, MAX_SETTLE_DURATION);
}
/**
* Clamp the magnitude of value for absMin and absMax.
* If the value is below the minimum, it will be clamped to zero.
* If the value is above the maximum, it will be clamped to the maximum.
*
* @param value Value to clamp
* @param absMin Absolute value of the minimum significant value to return
* @param absMax Absolute value of the maximum value to return
* @return The clamped value with the same sign as <code>value</code>
*/
private int clampMag(int value, int absMin, int absMax) {
final int absValue = Math.abs(value);
if (absValue < absMin) return 0;
if (absValue > absMax) return value > 0 ? absMax : -absMax;
return value;
}
/**
* Clamp the magnitude of value for absMin and absMax.
* If the value is below the minimum, it will be clamped to zero.
* If the value is above the maximum, it will be clamped to the maximum.
*
* @param value Value to clamp
* @param absMin Absolute value of the minimum significant value to return
* @param absMax Absolute value of the maximum value to return
* @return The clamped value with the same sign as <code>value</code>
*/
private float clampMag(float value, float absMin, float absMax) {
final float absValue = Math.abs(value);
if (absValue < absMin) return 0;
if (absValue > absMax) return value > 0 ? absMax : -absMax;
return value;
}
private float distanceInfluenceForSnapDuration(float f) {
f -= 0.5f; // center the values about 0.
f *= 0.3f * Math.PI / 2.0f;
return (float) Math.sin(f);
}
/**
* Move the captured settling view by the appropriate amount for the current time.
* If <code>continueSettling</code> returns true, the caller should call it again
* on the next frame to continue.
*
* @param deferCallbacks true if state callbacks should be deferred via posted message.
* Set this to true if you are calling this method from
* {@link android.view.View#computeScroll()} or similar methods
* invoked as part of layout or drawing.
* @return true if settle is still in progress
*/
public boolean continueSettling(boolean deferCallbacks) {
if (mDragState == STATE_SETTLING) {
boolean keepGoing = mScroller.computeScrollOffset();
final int x = mScroller.getCurrX();
final int y = mScroller.getCurrY();
final int dx = x - mCapturedView.getLeft();
final int dy = y - mCapturedView.getTop();
if (dx != 0) {
mCapturedView.offsetLeftAndRight(dx);
}
if (dy != 0) {
mCapturedView.offsetTopAndBottom(dy);
}
if (dx != 0 || dy != 0) {
mCallback.onViewPositionChanged(mCapturedView, x, y, dx, dy);
}
if (keepGoing && x == mScroller.getFinalX() && y == mScroller.getFinalY()) {
// Close enough. The interpolator/scroller might think we're still moving
// but the user sure doesn't.
mScroller.abortAnimation();
keepGoing = mScroller.isFinished();
}
if (!keepGoing) {
if (deferCallbacks) {
mParentView.post(mSetIdleRunnable);
} else {
setDragState(STATE_IDLE);
}
}
}
return mDragState == STATE_SETTLING;
}
/**
* Like all callback events this must happen on the UI thread, but release
* involves some extra semantics. During a release (mReleaseInProgress)
* is the only time it is valid to call {@link #settleCapturedViewAt(int, int)}
* or {@link #flingCapturedView(int, int, int, int)}.
*/
private void dispatchViewReleased(float xvel, float yvel) {
mReleaseInProgress = true;
mCallback.onViewReleased(mCapturedView, xvel, yvel);
mReleaseInProgress = false;
if (mDragState == STATE_DRAGGING) {
// onViewReleased didn't call a method that would have changed this. Go idle.
setDragState(STATE_IDLE);
}
}
private void clearMotionHistory() {
if (mInitialMotionX == null) {
return;
}
Arrays.fill(mInitialMotionX, 0);
Arrays.fill(mInitialMotionY, 0);
Arrays.fill(mLastMotionX, 0);
Arrays.fill(mLastMotionY, 0);
Arrays.fill(mInitialEdgesTouched, 0);
Arrays.fill(mEdgeDragsInProgress, 0);
Arrays.fill(mEdgeDragsLocked, 0);
mPointersDown = 0;
}
private void clearMotionHistory(int pointerId) {
if (mInitialMotionX == null) {
return;
}
mInitialMotionX[pointerId] = 0;
mInitialMotionY[pointerId] = 0;
mLastMotionX[pointerId] = 0;
mLastMotionY[pointerId] = 0;
mInitialEdgesTouched[pointerId] = 0;
mEdgeDragsInProgress[pointerId] = 0;
mEdgeDragsLocked[pointerId] = 0;
mPointersDown &= ~(1 << pointerId);
}
private void ensureMotionHistorySizeForId(int pointerId) {
if (mInitialMotionX == null || mInitialMotionX.length <= pointerId) {
float[] imx = new float[pointerId + 1];
float[] imy = new float[pointerId + 1];
float[] lmx = new float[pointerId + 1];
float[] lmy = new float[pointerId + 1];
int[] iit = new int[pointerId + 1];
int[] edip = new int[pointerId + 1];
int[] edl = new int[pointerId + 1];
if (mInitialMotionX != null) {
System.arraycopy(mInitialMotionX, 0, imx, 0, mInitialMotionX.length);
System.arraycopy(mInitialMotionY, 0, imy, 0, mInitialMotionY.length);
System.arraycopy(mLastMotionX, 0, lmx, 0, mLastMotionX.length);
System.arraycopy(mLastMotionY, 0, lmy, 0, mLastMotionY.length);
System.arraycopy(mInitialEdgesTouched, 0, iit, 0, mInitialEdgesTouched.length);
System.arraycopy(mEdgeDragsInProgress, 0, edip, 0, mEdgeDragsInProgress.length);
System.arraycopy(mEdgeDragsLocked, 0, edl, 0, mEdgeDragsLocked.length);
}
mInitialMotionX = imx;
mInitialMotionY = imy;
mLastMotionX = lmx;
mLastMotionY = lmy;
mInitialEdgesTouched = iit;
mEdgeDragsInProgress = edip;
mEdgeDragsLocked = edl;
}
}
private void saveInitialMotion(float x, float y, int pointerId) {
ensureMotionHistorySizeForId(pointerId);
mInitialMotionX[pointerId] = mLastMotionX[pointerId] = x;
mInitialMotionY[pointerId] = mLastMotionY[pointerId] = y;
mInitialEdgesTouched[pointerId] = getEdgesTouched((int) x, (int) y);
mPointersDown |= 1 << pointerId;
}
private void saveLastMotion(MotionEvent ev) {
final int pointerCount = MotionEventCompat.getPointerCount(ev);
for (int i = 0; i < pointerCount; i++) {
final int pointerId = MotionEventCompat.getPointerId(ev, i);
final float x = MotionEventCompat.getX(ev, i);
final float y = MotionEventCompat.getY(ev, i);
mLastMotionX[pointerId] = x;
mLastMotionY[pointerId] = y;
}
}
/**
* Check if the given pointer ID represents a pointer that is currently down (to the best
* of the ViewDragHelper's knowledge).
*
* <p>The state used to report this information is populated by the methods
* {@link #shouldInterceptTouchEvent(android.view.MotionEvent)} or
* {@link #processTouchEvent(android.view.MotionEvent)}. If one of these methods has not
* been called for all relevant MotionEvents to track, the information reported
* by this method may be stale or incorrect.</p>
*
* @param pointerId pointer ID to check; corresponds to IDs provided by MotionEvent
* @return true if the pointer with the given ID is still down
*/
public boolean isPointerDown(int pointerId) {
return (mPointersDown & 1 << pointerId) != 0;
}
void setDragState(int state) {
if (mDragState != state) {
mDragState = state;
mCallback.onViewDragStateChanged(state);
if (state == STATE_IDLE) {
mCapturedView = null;
}
}
}
/**
* Attempt to capture the view with the given pointer ID. The callback will be involved.
* This will put us into the "dragging" state. If we've already captured this view with
* this pointer this method will immediately return true without consulting the callback.
*
* @param toCapture View to capture
* @param pointerId Pointer to capture with
* @return true if capture was successful
*/
boolean tryCaptureViewForDrag(View toCapture, int pointerId) {
if (toCapture == mCapturedView && mActivePointerId == pointerId) {
// Already done!
return true;
}
if (toCapture != null && mCallback.tryCaptureView(toCapture, pointerId)) {
mActivePointerId = pointerId;
captureChildView(toCapture, pointerId);
return true;
}
return false;
}
/**
* Check if this event as provided to the parent view's onInterceptTouchEvent should
* cause the parent to intercept the touch event stream.
*
* @param ev MotionEvent provided to onInterceptTouchEvent
* @return true if the parent view should return true from onInterceptTouchEvent
*/
public boolean shouldInterceptTouchEvent(MotionEvent ev) {
final int action = MotionEventCompat.getActionMasked(ev);
final int actionIndex = MotionEventCompat.getActionIndex(ev);
if (action == MotionEvent.ACTION_DOWN) {
// Reset things for a new event stream, just in case we didn't get
// the whole previous stream.
cancel();
}
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(ev);
switch (action) {
case MotionEvent.ACTION_DOWN: {
final float x = ev.getX();
final float y = ev.getY();
final int pointerId = MotionEventCompat.getPointerId(ev, 0);
saveInitialMotion(x, y, pointerId);
final View toCapture = findTopChildUnder((int) x, (int) y);
// Catch a settling view if possible.
if (toCapture == mCapturedView && mDragState == STATE_SETTLING) {
tryCaptureViewForDrag(toCapture, pointerId);
}
final int edgesTouched = mInitialEdgesTouched[pointerId];
if ((edgesTouched & mTrackingEdges) != 0) {
mCallback.onEdgeTouched(edgesTouched & mTrackingEdges, pointerId);
}
break;
}
case MotionEventCompat.ACTION_POINTER_DOWN: {
final int pointerId = MotionEventCompat.getPointerId(ev, actionIndex);
final float x = MotionEventCompat.getX(ev, actionIndex);
final float y = MotionEventCompat.getY(ev, actionIndex);
saveInitialMotion(x, y, pointerId);
// A ViewDragHelper can only manipulate one view at a time.
if (mDragState == STATE_IDLE) {
final int edgesTouched = mInitialEdgesTouched[pointerId];
if ((edgesTouched & mTrackingEdges) != 0) {
mCallback.onEdgeTouched(edgesTouched & mTrackingEdges, pointerId);
}
} else if (mDragState == STATE_SETTLING) {
// Catch a settling view if possible.
final View toCapture = findTopChildUnder((int) x, (int) y);
if (toCapture == mCapturedView) {
tryCaptureViewForDrag(toCapture, pointerId);
}
}
break;
}
case MotionEvent.ACTION_MOVE: {
// First to cross a touch slop over a draggable view wins. Also report edge drags.
final int pointerCount = MotionEventCompat.getPointerCount(ev);
for (int i = 0; i < pointerCount && mInitialMotionX != null && mInitialMotionY != null; i++) {
final int pointerId = MotionEventCompat.getPointerId(ev, i);
final float x = MotionEventCompat.getX(ev, i);
final float y = MotionEventCompat.getY(ev, i);
final float dx = x - mInitialMotionX[pointerId];
final float dy = y - mInitialMotionY[pointerId];
reportNewEdgeDrags(dx, dy, pointerId);
if (mDragState == STATE_DRAGGING) {
// Callback might have started an edge drag
break;
}
final View toCapture = findTopChildUnder((int)mInitialMotionX[pointerId], (int)mInitialMotionY[pointerId]);
if (toCapture != null && checkTouchSlop(toCapture, dx, dy) &&
tryCaptureViewForDrag(toCapture, pointerId)) {
break;
}
}
saveLastMotion(ev);
break;
}
case MotionEventCompat.ACTION_POINTER_UP: {
final int pointerId = MotionEventCompat.getPointerId(ev, actionIndex);
clearMotionHistory(pointerId);
break;
}
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: {
cancel();
break;
}
}
return mDragState == STATE_DRAGGING;
}
/**
* Process a touch event received by the parent view. This method will dispatch callback events
* as needed before returning. The parent view's onTouchEvent implementation should call this.
*
* @param ev The touch event received by the parent view
*/
public void processTouchEvent(MotionEvent ev) {
final int action = MotionEventCompat.getActionMasked(ev);
final int actionIndex = MotionEventCompat.getActionIndex(ev);
if (action == MotionEvent.ACTION_DOWN) {
// Reset things for a new event stream, just in case we didn't get
// the whole previous stream.
cancel();
}
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(ev);
switch (action) {
case MotionEvent.ACTION_DOWN: {
final float x = ev.getX();
final float y = ev.getY();
final int pointerId = MotionEventCompat.getPointerId(ev, 0);
final View toCapture = findTopChildUnder((int) x, (int) y);
saveInitialMotion(x, y, pointerId);
// Since the parent is already directly processing this touch event,
// there is no reason to delay for a slop before dragging.
// Start immediately if possible.
tryCaptureViewForDrag(toCapture, pointerId);
final int edgesTouched = mInitialEdgesTouched[pointerId];
if ((edgesTouched & mTrackingEdges) != 0) {
mCallback.onEdgeTouched(edgesTouched & mTrackingEdges, pointerId);
}
break;
}
case MotionEventCompat.ACTION_POINTER_DOWN: {
final int pointerId = MotionEventCompat.getPointerId(ev, actionIndex);
final float x = MotionEventCompat.getX(ev, actionIndex);
final float y = MotionEventCompat.getY(ev, actionIndex);
saveInitialMotion(x, y, pointerId);
// A ViewDragHelper can only manipulate one view at a time.
if (mDragState == STATE_IDLE) {
// If we're idle we can do anything! Treat it like a normal down event.
final View toCapture = findTopChildUnder((int) x, (int) y);
tryCaptureViewForDrag(toCapture, pointerId);
final int edgesTouched = mInitialEdgesTouched[pointerId];
if ((edgesTouched & mTrackingEdges) != 0) {
mCallback.onEdgeTouched(edgesTouched & mTrackingEdges, pointerId);
}
} else if (isCapturedViewUnder((int) x, (int) y)) {
// We're still tracking a captured view. If the same view is under this
// point, we'll swap to controlling it with this pointer instead.
// (This will still work if we're "catching" a settling view.)
tryCaptureViewForDrag(mCapturedView, pointerId);
}
break;
}
case MotionEvent.ACTION_MOVE: {
if (mDragState == STATE_DRAGGING) {
final int index = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
final float x = MotionEventCompat.getX(ev, index);
final float y = MotionEventCompat.getY(ev, index);
final int idx = (int) (x - mLastMotionX[mActivePointerId]);
final int idy = (int) (y - mLastMotionY[mActivePointerId]);
dragTo(mCapturedView.getLeft() + idx, mCapturedView.getTop() + idy, idx, idy);
saveLastMotion(ev);
} else {
// Check to see if any pointer is now over a draggable view.
final int pointerCount = MotionEventCompat.getPointerCount(ev);
for (int i = 0; i < pointerCount; i++) {
final int pointerId = MotionEventCompat.getPointerId(ev, i);
final float x = MotionEventCompat.getX(ev, i);
final float y = MotionEventCompat.getY(ev, i);
final float dx = x - mInitialMotionX[pointerId];
final float dy = y - mInitialMotionY[pointerId];
reportNewEdgeDrags(dx, dy, pointerId);
if (mDragState == STATE_DRAGGING) {
// Callback might have started an edge drag.
break;
}
final View toCapture = findTopChildUnder((int) x, (int) y);
if (checkTouchSlop(toCapture, dx, dy) &&
tryCaptureViewForDrag(toCapture, pointerId)) {
break;
}
}
saveLastMotion(ev);
}
break;
}
case MotionEventCompat.ACTION_POINTER_UP: {
final int pointerId = MotionEventCompat.getPointerId(ev, actionIndex);
if (mDragState == STATE_DRAGGING && pointerId == mActivePointerId) {
// Try to find another pointer that's still holding on to the captured view.
int newActivePointer = INVALID_POINTER;
final int pointerCount = MotionEventCompat.getPointerCount(ev);
for (int i = 0; i < pointerCount; i++) {
final int id = MotionEventCompat.getPointerId(ev, i);
if (id == mActivePointerId) {
// This one's going away, skip.
continue;
}
final float x = MotionEventCompat.getX(ev, i);
final float y = MotionEventCompat.getY(ev, i);
if (findTopChildUnder((int) x, (int) y) == mCapturedView &&
tryCaptureViewForDrag(mCapturedView, id)) {
newActivePointer = mActivePointerId;
break;
}
}
if (newActivePointer == INVALID_POINTER) {
// We didn't find another pointer still touching the view, release it.
releaseViewForPointerUp();
}
}
clearMotionHistory(pointerId);
break;
}
case MotionEvent.ACTION_UP: {
if (mDragState == STATE_DRAGGING) {
releaseViewForPointerUp();
}
cancel();
break;
}
case MotionEvent.ACTION_CANCEL: {
if (mDragState == STATE_DRAGGING) {
dispatchViewReleased(0, 0);
}
cancel();
break;
}
}
}
private void reportNewEdgeDrags(float dx, float dy, int pointerId) {
int dragsStarted = 0;
if (checkNewEdgeDrag(dx, dy, pointerId, EDGE_LEFT)) {
dragsStarted |= EDGE_LEFT;
}
if (checkNewEdgeDrag(dy, dx, pointerId, EDGE_TOP)) {
dragsStarted |= EDGE_TOP;
}
if (checkNewEdgeDrag(dx, dy, pointerId, EDGE_RIGHT)) {
dragsStarted |= EDGE_RIGHT;
}
if (checkNewEdgeDrag(dy, dx, pointerId, EDGE_BOTTOM)) {
dragsStarted |= EDGE_BOTTOM;
}
if (dragsStarted != 0) {
mEdgeDragsInProgress[pointerId] |= dragsStarted;
mCallback.onEdgeDragStarted(dragsStarted, pointerId);
}
}
private boolean checkNewEdgeDrag(float delta, float odelta, int pointerId, int edge) {
final float absDelta = Math.abs(delta);
final float absODelta = Math.abs(odelta);
if ((mInitialEdgesTouched[pointerId] & edge) != edge || (mTrackingEdges & edge) == 0 ||
(mEdgeDragsLocked[pointerId] & edge) == edge ||
(mEdgeDragsInProgress[pointerId] & edge) == edge ||
(absDelta <= mTouchSlop && absODelta <= mTouchSlop)) {
return false;
}
if (absDelta < absODelta * 0.5f && mCallback.onEdgeLock(edge)) {
mEdgeDragsLocked[pointerId] |= edge;
return false;
}
return (mEdgeDragsInProgress[pointerId] & edge) == 0 && absDelta > mTouchSlop;
}
/**
* Check if we've crossed a reasonable touch slop for the given child view.
* If the child cannot be dragged along the horizontal or vertical axis, motion
* along that axis will not count toward the slop check.
*
* @param child Child to check
* @param dx Motion since initial position along X axis
* @param dy Motion since initial position along Y axis
* @return true if the touch slop has been crossed
*/
private boolean checkTouchSlop(View child, float dx, float dy) {
if (child == null) {
return false;
}
final boolean checkHorizontal = mCallback.getViewHorizontalDragRange(child) > 0;
final boolean checkVertical = mCallback.getViewVerticalDragRange(child) > 0;
if (checkHorizontal && checkVertical) {
return dx * dx + dy * dy > mTouchSlop * mTouchSlop;
} else if (checkHorizontal) {
return Math.abs(dx) > mTouchSlop;
} else if (checkVertical) {
return Math.abs(dy) > mTouchSlop;
}
return false;
}
private void releaseViewForPointerUp() {
mVelocityTracker.computeCurrentVelocity(1000, mMaxVelocity);
final float xvel = clampMag(
VelocityTrackerCompat.getXVelocity(mVelocityTracker, mActivePointerId),
mMinVelocity, mMaxVelocity);
final float yvel = clampMag(
VelocityTrackerCompat.getYVelocity(mVelocityTracker, mActivePointerId),
mMinVelocity, mMaxVelocity);
dispatchViewReleased(xvel, yvel);
}
private void dragTo(int left, int top, int dx, int dy) {
int clampedX = left;
int clampedY = top;
final int oldLeft = mCapturedView.getLeft();
final int oldTop = mCapturedView.getTop();
if (dx != 0) {
clampedX = mCallback.clampViewPositionHorizontal(mCapturedView, left, dx);
mCapturedView.offsetLeftAndRight(clampedX - oldLeft);
}
if (dy != 0) {
clampedY = mCallback.clampViewPositionVertical(mCapturedView, top, dy);
mCapturedView.offsetTopAndBottom(clampedY - oldTop);
}
if (dx != 0 || dy != 0) {
final int clampedDx = clampedX - oldLeft;
final int clampedDy = clampedY - oldTop;
mCallback.onViewPositionChanged(mCapturedView, clampedX, clampedY,
clampedDx, clampedDy);
}
}
/**
* Determine if the currently captured view is under the given point in the
* parent view's coordinate system. If there is no captured view this method
* will return false.
*
* @param x X position to test in the parent's coordinate system
* @param y Y position to test in the parent's coordinate system
* @return true if the captured view is under the given point, false otherwise
*/
public boolean isCapturedViewUnder(int x, int y) {
return isViewUnder(mCapturedView, x, y);
}
/**
* Determine if the supplied view is under the given point in the
* parent view's coordinate system.
*
* @param view Child view of the parent to hit test
* @param x X position to test in the parent's coordinate system
* @param y Y position to test in the parent's coordinate system
* @return true if the supplied view is under the given point, false otherwise
*/
public boolean isViewUnder(View view, int x, int y) {
if (view == null) {
return false;
}
return x >= view.getLeft() &&
x < view.getRight() &&
y >= view.getTop() &&
y < view.getBottom();
}
/**
* Find the topmost child under the given point within the parent view's coordinate system.
* The child order is determined using {@link Callback#getOrderedChildIndex(int)}.
*
* @param x X position to test in the parent's coordinate system
* @param y Y position to test in the parent's coordinate system
* @return The topmost child view under (x, y) or null if none found.
*/
public View findTopChildUnder(int x, int y) {
final int childCount = mParentView.getChildCount();
for (int i = childCount - 1; i >= 0; i--) {
final View child = mParentView.getChildAt(mCallback.getOrderedChildIndex(i));
if (x >= child.getLeft() && x < child.getRight() &&
y >= child.getTop() && y < child.getBottom()) {
return child;
}
}
return null;
}
private int getEdgesTouched(int x, int y) {
int result = 0;
if (x < mParentView.getLeft() + mEdgeSize) result |= EDGE_LEFT;
if (y < mParentView.getTop() + mEdgeSize) result |= EDGE_TOP;
if (x > mParentView.getRight() - mEdgeSize) result |= EDGE_RIGHT;
if (y > mParentView.getBottom() - mEdgeSize) result |= EDGE_BOTTOM;
return result;
}
}
\ No newline at end of file
package com.mrane.zoomview;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Join;
import android.graphics.Paint.Style;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.BounceInterpolator;
import app.insti.R.drawable;
import app.insti.fragment.MapFragment;
import com.mrane.campusmap.SettingsManager;
import com.mrane.data.Building;
import com.mrane.data.Marker;
import com.mrane.data.Room;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
public class CampusMapView extends SubsamplingScaleImageView {
private MapFragment mainActivity;
private HashMap<String, Marker> data;
private Collection<Marker> markerList;
private ArrayList<Marker> addedMarkerList;
private ArrayList<Marker> specialMarkerList;
private ArrayList<Marker> convoMarkerList;
private Marker resultMarker;
private Bitmap bluePointer;
private Bitmap yellowPointer;
private Bitmap greenPointer;
private Bitmap grayPointer;
private Bitmap blueMarker;
private Bitmap yellowMarker;
private Bitmap greenMarker;
private Bitmap grayMarker;
private Bitmap blueLockedMarker;
private Bitmap blueConvoMarker;
private Bitmap yellowLockedMarker;
private Bitmap greenLockedMarker;
private Bitmap grayLockedMarker;
private float pointerWidth = 12;
private float highlightedMarkerScale;
private Paint paint;
private Paint textPaint;
private Paint strokePaint;
private Rect bounds = new Rect();
private static int RATIO_SHOW_PIN = 10;
private static int RATIO_SHOW_PIN_TEXT = 20;
private static long DURATION_MARKER_ANIMATION = 500;
private static long DELAY_MARKER_ANIMATION = 675;
private static float MAX_SCALE = 1F;
private DisplayMetrics displayMetrics;
private float density;
private boolean isFirstLoad = true;
private SettingsManager settingsManager;
public CampusMapView(Context context) {
this(context, null);
}
public CampusMapView(Context context, AttributeSet attr) {
super(context, attr);
initialise();
}
private void initialise() {
displayMetrics = getResources().getDisplayMetrics();
density = displayMetrics.density;
highlightedMarkerScale = 1.0f;
initMarkers();
initPaints();
mainActivity = MapFragment.getMainActivity();
setGestureDetector();
super.setMaxScale(density * MAX_SCALE);
}
@Override
protected void onImageReady() {
if (isFirstLoad) {
Runnable runnable = new Runnable() {
public void run() {
AnimationBuilder anim;
anim = animateScaleAndCenter(
getTargetMinScale(), MapFragment.MAP_CENTER);
anim.withDuration(MapFragment.DURATION_INIT_MAP_ANIM)
.start();
isFirstLoad = false;
}
};
mainActivity.getActivity().runOnUiThread(runnable);
}
}
public void setSettingsManager(SettingsManager sm){
settingsManager = sm;
}
public void setFirstLoad(boolean b) {
isFirstLoad = b;
}
private void initMarkers() {
float w = 0;
float h = 0;
Options options = new BitmapFactory.Options();
options.inScaled = true;
bluePointer = BitmapFactory.decodeResource(getResources(),
drawable.marker_dot_blue, options);
blueMarker = BitmapFactory.decodeResource(getResources(),
drawable.marker_blue_s, options);
blueLockedMarker = BitmapFactory.decodeResource(getResources(),
drawable.marker_blue_h, options);
blueConvoMarker = BitmapFactory.decodeResource(getResources(),
drawable.marker_blue_h_convo, options);
yellowPointer = BitmapFactory.decodeResource(getResources(),
drawable.marker_dot_yellow, options);
yellowMarker = BitmapFactory.decodeResource(getResources(),
drawable.marker_yellow_s, options);
yellowLockedMarker = BitmapFactory.decodeResource(getResources(),
drawable.marker_yellow_h, options);
greenPointer = BitmapFactory.decodeResource(getResources(),
drawable.marker_dot_green, options);
greenMarker = BitmapFactory.decodeResource(getResources(),
drawable.marker_green_s, options);
greenLockedMarker = BitmapFactory.decodeResource(getResources(),
drawable.marker_green_h, options);
grayPointer = BitmapFactory.decodeResource(getResources(),
drawable.marker_dot_gray, options);
grayMarker = BitmapFactory.decodeResource(getResources(),
drawable.marker_gray_s, options);
grayLockedMarker = BitmapFactory.decodeResource(getResources(),
drawable.marker_gray_h, options);
w = pointerWidth*density;
h = bluePointer.getScaledHeight(displayMetrics) * (w / bluePointer.getScaledWidth(displayMetrics));
bluePointer = Bitmap.createScaledBitmap(bluePointer, (int) w, (int) h,
true);
bluePointer = Bitmap.createScaledBitmap(bluePointer, (int) w, (int) h,
true);
yellowPointer = Bitmap.createScaledBitmap(yellowPointer, (int) w,
(int) h, true);
greenPointer = Bitmap.createScaledBitmap(greenPointer, (int) w,
(int) h, true);
grayPointer = Bitmap.createScaledBitmap(grayPointer, (int) w, (int) h,
true);
w = 4f * w;
h = blueMarker.getScaledHeight(displayMetrics) * (w / blueMarker.getScaledWidth(displayMetrics));
blueMarker = Bitmap.createScaledBitmap(blueMarker, (int) w, (int) h,
true);
yellowMarker = Bitmap.createScaledBitmap(yellowMarker, (int) w,
(int) h, true);
greenMarker = Bitmap.createScaledBitmap(greenMarker, (int) w, (int) h,
true);
grayMarker = Bitmap.createScaledBitmap(grayMarker, (int) w, (int) h,
true);
blueLockedMarker = Bitmap.createScaledBitmap(blueLockedMarker, (int) w,
(int) h, true);
blueConvoMarker = Bitmap.createScaledBitmap(blueConvoMarker, (int) w,
(int) h, true);
yellowLockedMarker = Bitmap.createScaledBitmap(yellowLockedMarker,
(int) w, (int) h, true);
greenLockedMarker = Bitmap.createScaledBitmap(greenLockedMarker,
(int) w, (int) h, true);
grayLockedMarker = Bitmap.createScaledBitmap(grayLockedMarker, (int) w,
(int) h, true);
}
private void initPaints() {
paint = new Paint();
paint.setAntiAlias(true);
textPaint = new Paint();
textPaint.setAntiAlias(true);
// textPaint.setColor(Color.rgb(254, 250, 217));
textPaint.setColor(Color.WHITE);
textPaint.setShadowLayer(8.0f * density, -1 * density, 1 * density,
Color.BLACK);
textPaint.setTextSize(16 * density);
Typeface boldCn = Typeface.createFromAsset(getContext().getAssets(),
MapFragment.FONT_SEMIBOLD);
textPaint.setTypeface(boldCn);
strokePaint = new Paint();
strokePaint.setAntiAlias(true);
strokePaint.setColor(Color.BLACK);
strokePaint.setTypeface(Typeface.DEFAULT_BOLD);
strokePaint.setTextSize(14 * density);
strokePaint.setStyle(Style.STROKE);
strokePaint.setStrokeJoin(Join.ROUND);
strokePaint.setStrokeWidth(0.2f * density);
}
public float getTargetMinScale() {
return Math.max(getWidth() / (float) getSWidth(), (getHeight())
/ (float) getSHeight());
}
public void setData(HashMap<String, Marker> markerData) {
data = markerData;
markerList = data.values();
addedMarkerList = new ArrayList<Marker>();
specialMarkerList = new ArrayList<Marker>();
convoMarkerList = new ArrayList<Marker>();
setSpecialMarkers();
}
private void setSpecialMarkers() {
for (Marker m : markerList) {
if (m.isShowDefault()) {
specialMarkerList.add(m);
}
}
}
public static int getShowPinRatio() {
return RATIO_SHOW_PIN;
}
public static void setShowPinRatio(int ratio) {
RATIO_SHOW_PIN = ratio;
}
public static int getShowPinTextRatio() {
return RATIO_SHOW_PIN_TEXT;
}
public static void setShowPinTextRatio(int ratio) {
RATIO_SHOW_PIN_TEXT = ratio;
}
public Marker getResultMarker() {
return resultMarker;
}
@Deprecated
public Marker getHighlightedMarker() {
return getResultMarker();
}
public void setResultMarker(Marker marker) {
resultMarker = marker;
}
public boolean isResultMarker(Marker marker) {
if (resultMarker == null)
return false;
return resultMarker == marker;
}
public void showResultMarker() {
if (resultMarker != null) {
boolean noDelay = false;
if (isInView(getResultMarker().getPoint()))
noDelay = true;
AnimationBuilder anim = animateScaleAndCenter(getShowTextScale(),
resultMarker.getPoint());
anim.withDuration(750).start();
setMarkerAnimation(noDelay, MapFragment.SOUND_ID_RESULT);
}
}
public void setAndShowResultMarker(Marker marker) {
setResultMarker(marker);
showResultMarker();
}
public void addMarker(Marker m) {
if (!addedMarkerList.contains(m)) {
addedMarkerList.add(m);
}
}
public void addMarker() {
Marker m = getResultMarker();
addMarker(m);
}
public void addMarkers(Collection<? extends Marker> markers) {
for (Marker m : markers) {
addMarker(m);
}
}
public void addMarkers(Marker[] markerArray) {
List<Marker> markerList = Arrays.asList(markerArray);
addMarkers(markerList);
}
public void removeAddedMarker(Marker m) {
if (addedMarkerList.contains(m)) {
addedMarkerList.remove(m);
}
}
public void removeAddedMarkers(Collection<? extends Marker> markers) {
for (Marker m : markers) {
removeAddedMarker(m);
}
}
public void removeAddedMarkers(Marker[] markerArray) {
List<Marker> markerList = Arrays.asList(markerArray);
removeAddedMarkers(markerList);
}
public void removeAddedMarkers() {
addedMarkerList.clear();
}
public boolean isAddedMarker(Marker m) {
return addedMarkerList.contains(m);
}
public boolean isAddedMarker() {
return isAddedMarker(getResultMarker());
}
public void toggleMarker(Marker m) {
if (isAddedMarker(m)) {
removeAddedMarker(m);
mainActivity.playAnimSound(MapFragment.SOUND_ID_REMOVE);
} else {
addMarker(m);
if (!isInView(m.getPoint())) {
AnimationBuilder anim = animateScaleAndCenter(
getShowTextScale(), m.getPoint());
anim.withDuration(750).start();
setMarkerAnimation(false, MapFragment.SOUND_ID_ADD);
} else {
setMarkerAnimation(true, MapFragment.SOUND_ID_ADD);
}
}
invalidate();
}
public void toggleMarker() {
toggleMarker(getResultMarker());
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// Don't draw pin before image is ready so it doesn't move around during
// setup.
if (!isImageReady()) {
return;
}
for (Marker marker : markerList) {
if (isInView(marker.getPoint())) {
if (isShowPinScale(marker)
&& !(isResultMarker(marker) || addedMarkerList
.contains(marker))) {
if (shouldShowUp(marker))
drawPionterAndText(canvas, marker);
}
}
}
for (Marker marker : addedMarkerList) {
if (isInView(marker.getPoint())) {
if (!isResultMarker(marker)) {
drawMarkerBitmap(canvas, marker);
drawMarkerText(canvas, marker);
}
}
}
Marker marker = getResultMarker();
if (marker != null) {
if (isInView(marker.getPoint())) {
drawMarkerBitmap(canvas, marker);
drawMarkerText(canvas, marker);
}
}
}
private boolean shouldShowUp(Marker marker) {
boolean result = true;
if(marker.getGroupIndex() == Marker.RESIDENCES){
result = settingsManager.showResidences();
}
if (marker instanceof Building) {
String[] childKeys = ((Building) marker).children;
for (String childKey : childKeys) {
Marker child = data.get(childKey);
if (isAddedMarker(child) || isResultMarker(child)) {
result = false;
break;
}
}
}
if (marker instanceof Room)
result = false;
return result;
}
private void drawMarkerBitmap(Canvas canvas, Marker marker) {
Bitmap highlightedPin = getMarkerBitmap(marker);
PointF vPin = sourceToViewCoord(marker.getPoint());
float vX = vPin.x - (highlightedPin.getWidth() / 2);
float vY = vPin.y - highlightedPin.getHeight();
canvas.drawBitmap(highlightedPin, vX, vY, paint);
}
private void drawMarkerText(Canvas canvas, Marker marker) {
String name;
PointF vPin = sourceToViewCoord(marker.getPoint());
if (marker.getShortName().equals("0") || marker.getShortName().isEmpty())
name = marker.getName();
else
name = marker.getShortName();
textPaint.getTextBounds(name, 0, name.length() - 1, bounds);
float tX = vPin.x - bounds.width() / 2;
float tY = vPin.y + bounds.height();
canvas.drawText(name, tX, tY, textPaint);
// canvas.drawText(names[0], tX, tY, strokePaint);
}
private void drawPionterAndText(Canvas canvas, Marker marker) {
Bitmap pin = getPointerBitmap(marker);
PointF vPin = sourceToViewCoord(marker.getPoint());
float vX = vPin.x - (pin.getWidth() / 2);
float vY = vPin.y - (pin.getHeight() / 2);
canvas.drawBitmap(pin, vX, vY, paint);
if (isShowPinTextScale(marker)) {
String name;
if (marker.getShortName().equals("0") || marker.getShortName().isEmpty())
name = marker.getName();
else
name = marker.getShortName();
Paint temp = new Paint(textPaint);
if(marker.getGroupIndex() == Marker.RESIDENCES) temp.setTextSize(12*density);
textPaint.getTextBounds(name, 0, name.length() - 1, bounds);
float tX = vPin.x + pin.getWidth();
float tY = vPin.y + bounds.height() / 2;
canvas.drawText(name, tX, tY, temp);
}
}
private boolean isInView(PointF point) {
int displayWidth = displayMetrics.widthPixels;
int displayHeight = displayMetrics.heightPixels;
int viewX = (int) sourceToViewCoord(point).x;
int viewY = (int) sourceToViewCoord(point).y;
if (viewX > -displayWidth / 3 && viewX < displayWidth && viewY > 0
&& viewY < displayHeight)
return true;
return false;
}
private Marker getNearestMarker(PointF touchPoint) {
Marker resultMarker = null;
float minDist = 100000000f;
for (Marker marker : markerList) {
PointF point = marker.getPoint();
float dist = (float) calculateDistance(point, touchPoint);
if (dist < minDist && isMarkerVisible(marker)) {
minDist = dist;
resultMarker = marker;
}
}
return resultMarker;
}
private double calculateDistance(PointF point1, PointF point2) {
float xDiff = point1.x - point2.x;
float yDiff = point1.y - point2.y;
return Math.sqrt(xDiff * xDiff + yDiff * yDiff);
}
private Bitmap getPointerBitmap(Marker marker) {
int color = marker.getColor();
if (color == Marker.COLOR_BLUE) {
return bluePointer;
} else if (color == Marker.COLOR_YELLOW) {
return yellowPointer;
} else if (color == Marker.COLOR_GREEN) {
return greenPointer;
} else if (color == Marker.COLOR_GRAY) {
return grayPointer;
}
return bluePointer;
}
private Bitmap getMarkerBitmap(Marker marker) {
int color = marker.getColor();
Bitmap markerBitmap = null;
if (color == Marker.COLOR_BLUE) {
markerBitmap = blueMarker;
if (isAddedMarker(marker)){
markerBitmap = blueLockedMarker;
if(convoMarkerList.contains(marker)) markerBitmap = blueConvoMarker;
}
} else if (color == Marker.COLOR_YELLOW) {
markerBitmap = yellowMarker;
if (isAddedMarker(marker))
markerBitmap = yellowLockedMarker;
} else if (color == Marker.COLOR_GREEN) {
markerBitmap = greenMarker;
if (isAddedMarker(marker))
markerBitmap = greenLockedMarker;
} else if (color == Marker.COLOR_GRAY) {
markerBitmap = grayMarker;
if (isAddedMarker(marker))
markerBitmap = grayLockedMarker;
}
if (highlightedMarkerScale != 1.0f && isResultMarker(marker)) {
float w = markerBitmap.getWidth() * highlightedMarkerScale;
float h = markerBitmap.getHeight() * highlightedMarkerScale;
markerBitmap = Bitmap.createScaledBitmap(markerBitmap, (int) w,
(int) h, true);
}
if (isResultMarker(marker)) {
float w = markerBitmap.getWidth() * 1.2f;
float h = markerBitmap.getHeight() * 1.2f;
markerBitmap = Bitmap.createScaledBitmap(markerBitmap, (int) w,
(int) h, true);
}
return markerBitmap;
}
private void setMarkerAnimation(boolean noDelay, int _sound_index) {
final int sound_index = _sound_index;
long delay = 0;
if (!noDelay) {
delay = DELAY_MARKER_ANIMATION;
}
if (android.os.Build.VERSION.SDK_INT >= 11) {
playAnim(delay);
} else {
highlightedMarkerScale = 1.0f;
}
mainActivity.playAnimSoundDelayed(sound_index, delay);
if (isImageReady())
invalidate();
}
@SuppressLint("NewApi")
private void playAnim(long delay) {
highlightedMarkerScale = 0.1f;
ValueAnimator valAnim = new ValueAnimator();
valAnim.setFloatValues(0.1f, 1.0f);
valAnim.setDuration(DURATION_MARKER_ANIMATION);
valAnim.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
highlightedMarkerScale = (Float) animation.getAnimatedValue();
if (isImageReady())
invalidate();
}
});
TimeInterpolator i = new BounceInterpolator();
valAnim.setInterpolator(i);
valAnim.setStartDelay(delay);
valAnim.start();
}
public Runnable getScaleAnim(final float scale){
Runnable anim = new Runnable() {
public void run() {
AnimationBuilder animation = animateScale(scale);
animation
.withDuration(200)
.withEasing(
SubsamplingScaleImageView.EASE_OUT_QUAD)
.start();
}
};
return anim;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if(getTargetMinScale() > getScale()){
setScaleAndCenter(getTargetMinScale(), getCenter());
}
super.onSizeChanged(w, h, oldw, oldh);
}
private void setGestureDetector() {
final GestureDetector gestureDetector = new GestureDetector(
mainActivity.getContext(), new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
if (isImageReady()) {
PointF sCoord = viewToSourceCoord(e.getX(),
e.getY());
Marker marker = getNearestMarker(sCoord);
if (isMarkerInTouchRegion(marker, sCoord)) {
// mMainActivity.resultMarker(marker.name);
mainActivity.editText.setText(marker.getName());
mainActivity.displayMap();
}
} else {
}
return true;
}
});
setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
final float targetMinScale = getTargetMinScale();
int action = motionEvent.getAction();
if(action== MotionEvent.ACTION_DOWN){
if(motionEvent.getX()<20*density){
getParent().requestDisallowInterceptTouchEvent(false);
return true;
}
else{
// CampusMapView.this.setPanEnabled(true);
}
}
else if(action == MotionEvent.ACTION_UP){
CampusMapView.this.setPanEnabled(true);
}
if (targetMinScale > getScale()) {
callSuperOnTouch(motionEvent);
if (action == MotionEvent.ACTION_UP) {
Runnable anim = getScaleAnim(targetMinScale);
if(isImageReady()) anim.run();
}
return true;
}
return gestureDetector.onTouchEvent(motionEvent);
}
});
}
private void callSuperOnTouch(MotionEvent me) {
super.onTouchEvent(me);
}
private boolean isMarkerInTouchRegion(Marker marker, PointF o) {
if (marker != null) {
PointF point = sourceToViewCoord(marker.getPoint());
PointF origin = sourceToViewCoord(o);
float dist = (float) calculateDistance(point, origin);
if (dist < pointerWidth * density * 2 && isMarkerVisible(marker)) {
return true;
}
}
return false;
}
private boolean isMarkerVisible(Marker marker) {
if (marker == resultMarker)
return true;
if (addedMarkerList.contains(marker))
return true;
if (isShowPinScale(marker) && shouldShowUp(marker))
return true;
return false;
}
private boolean isShowPinScale(Marker m) {
if (specialMarkerList.contains(m))
return true;
PointF left = viewToSourceCoord(0, 0);
PointF right = viewToSourceCoord(getWidth(), 0);
float xDpi = displayMetrics.xdpi;
if ((right.x - left.x) * xDpi / getWidth() < getSWidth()
/ RATIO_SHOW_PIN)
return true;
return false;
}
private boolean isShowPinTextScale(Marker m) {
if (specialMarkerList.contains(m))
return true;
// PointF left = viewToSourceCoord(0, 0);
// PointF right = viewToSourceCoord(getWidth(), 0);
// float xDpi = displayMetrics.xdpi;
// if((right.x-left.x)*xDpi/getWidth() <
// getSWidth()*density/(RATIO_SHOW_PIN_TEXT*2)) return true;
if (getScale() >= (getShowTextScale()))
return true;
return false;
}
private float getShowTextScale() {
float xDpi = displayMetrics.xdpi;
float scale = (RATIO_SHOW_PIN_TEXT * xDpi * 2 / density + 20)
/ getSWidth();
if (scale > getMaxScale()) {
scale = 0.7f * getMaxScale();
}
return scale;
}
// public void setAddedMarkers(String addedMarkerString) {
// addedMarkerList = new ArrayList<Marker>();
// String[] addedMarkerNames = addedMarkerString.split("###");
// for (String s : addedMarkerNames) {
// if (!s.equals("")) {
// Log.d("test123","names = " + s);
// if (data.containsKey(s)) {
// addedMarkerList.add(data.get(s));
// }
// }
// }
// }
//
// public String getAddedMarkerString() {
// String s = "";
// for (Marker m : addedMarkerList) {
// s = s + m.name + "###";
// }
// Log.d("test123","addedMarkerStringGen = " + s);
// return s;
// }
}
/*
Copyright 2014 David Morrissey
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 com.mrane.zoomview;
import android.graphics.PointF;
import java.io.Serializable;
/**
* Wraps the scale, center and orientation of a displayed image for easy restoration on screen rotate.
*/
public class ImageViewState implements Serializable {
/**
*
*/
private static final long serialVersionUID = -4397017033346987595L;
private float scale;
private float centerX;
private float centerY;
private int orientation;
public ImageViewState(float scale, PointF center, int orientation) {
this.scale = scale;
this.centerX = center.x;
this.centerY = center.y;
this.orientation = orientation;
}
public float getScale() {
return scale;
}
public PointF getCenter() {
return new PointF(centerX, centerY);
}
public int getOrientation() {
return orientation;
}
}
/*
Copyright 2014 David Morrissey
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 com.mrane.zoomview;
import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.BitmapRegionDecoder;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.media.ExifInterface;
import android.os.AsyncTask;
import android.os.Build.VERSION;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import app.insti.R.styleable;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Displays an image subsampled as necessary to avoid loading too much image data into memory. After a pinch to zoom in,
* a set of image tiles subsampled at higher resolution are loaded and displayed over the base layer. During pinch and
* zoom, tiles off screen or higher/lower resolution than required are discarded from memory.
*
* Tiles over 2048px are not used due to hardware rendering limitations.
*
* This view will not work very well with images that are far larger in one dimension than the other because the tile grid
* for each subsampling level has the same number of rows as columns, so each tile has the same width:height ratio as
* the source image. This could result in image data totalling several times the screen area being loaded.
*
* v prefixes - coordinates, translations and distances measured in screen (view) pixels
* s prefixes - coordinates, translations and distances measured in source image pixels (scaled)
*/
@SuppressWarnings("unused")
public class SubsamplingScaleImageView extends View {
private static final String TAG = SubsamplingScaleImageView.class.getSimpleName();
/** Attempt to use EXIF information on the image to rotate it. Works for external files only. */
public static final int ORIENTATION_USE_EXIF = -1;
/** Display the image file in its native orientation. */
public static final int ORIENTATION_0 = 0;
/** Rotate the image 90 degrees clockwise. */
public static final int ORIENTATION_90 = 90;
/** Rotate the image 180 degrees. */
public static final int ORIENTATION_180 = 180;
/** Rotate the image 270 degrees clockwise. */
public static final int ORIENTATION_270 = 270;
private static final List<Integer> VALID_ORIENTATIONS = Arrays.asList(ORIENTATION_0, ORIENTATION_90, ORIENTATION_180, ORIENTATION_270, ORIENTATION_USE_EXIF);
/** During zoom animation, keep the point of the image that was tapped in the same place, and scale the image around it. */
public static final int ZOOM_FOCUS_FIXED = 1;
/** During zoom animation, move the point of the image that was tapped to the center of the screen. */
public static final int ZOOM_FOCUS_CENTER = 2;
/** Zoom in to and center the tapped point immediately without animating. */
public static final int ZOOM_FOCUS_CENTER_IMMEDIATE = 3;
private static final List<Integer> VALID_ZOOM_STYLES = Arrays.asList(ZOOM_FOCUS_FIXED, ZOOM_FOCUS_CENTER, ZOOM_FOCUS_CENTER_IMMEDIATE);
/** Quadratic ease out. Not recommended for scale animation, but good for panning. */
public static final int EASE_OUT_QUAD = 1;
/** Quadratic ease in and out. */
public static final int EASE_IN_OUT_QUAD = 2;
private static final List<Integer> VALID_EASING_STYLES = Arrays.asList(EASE_IN_OUT_QUAD, EASE_OUT_QUAD);
/** Don't allow the image to be panned off screen. As much of the image as possible is always displayed, centered in the view when it is smaller. This is the best option for galleries. */
public static final int PAN_LIMIT_INSIDE = 1;
/** Allows the image to be panned until it is just off screen, but no further. The edge of the image will stop when it is flush with the screen edge. */
public static final int PAN_LIMIT_OUTSIDE = 2;
/** Allows the image to be panned until a corner reaches the center of the screen but no further. Useful when you want to pan any spot on the image to the exact center of the screen. */
public static final int PAN_LIMIT_CUSTOM = 3;
private static final List<Integer> VALID_PAN_LIMITS = Arrays.asList(PAN_LIMIT_INSIDE, PAN_LIMIT_OUTSIDE, PAN_LIMIT_CUSTOM);
// Overlay tile boundaries and other info
private boolean debug = false;
// Image orientation setting
private int orientation = ORIENTATION_0;
// Max scale allowed (prevent infinite zoom)
private float maxScale = 2F;
// Density to reach before loading higher resolution tiles
private int minimumTileDpi = -1;
// Pan limiting style
private int panLimit = PAN_LIMIT_INSIDE;
// Gesture detection settings
private boolean panEnabled = true;
private boolean zoomEnabled = true;
// Double tap zoom behaviour
private float doubleTapZoomScale = 1F;
private int doubleTapZoomStyle = ZOOM_FOCUS_FIXED;
// Current scale and scale at start of zoom
private float scale;
private float scaleStart;
// Screen coordinate of top-left corner of source image
private PointF vTranslate;
private PointF vTranslateStart;
// Source coordinate to center on, used when new position is set externally before view is ready
private Float pendingScale;
private PointF sPendingCenter;
private PointF sRequestedCenter;
// Source image dimensions and orientation - dimensions relate to the unrotated image
private int sWidth;
private int sHeight;
private int sOrientation;
// Is two-finger zooming in progress
private boolean isZooming;
// Is one-finger panning in progress
private boolean isPanning;
// Max touches used in current gesture
private int maxTouchCount;
// Fling detector
private GestureDetector detector;
// Tile decoder
private BitmapRegionDecoder decoder;
private final Object decoderLock = new Object();
// Sample size used to display the whole image when fully zoomed out
private int fullImageSampleSize;
// Map of zoom level to tile grid
private Map<Integer, List<Tile>> tileMap;
// Debug values
private PointF vCenterStart;
private float vDistStart;
// Scale and center animation tracking
private Anim anim;
// Whether a ready notification has been sent to subclasses
private boolean readySent = false;
// Long click listener
private OnLongClickListener onLongClickListener;
// Long click handler
private Handler handler;
private static final int MESSAGE_LONG_CLICK = 1;
// Paint objects created once and reused for efficiency
private Paint bitmapPaint;
private Paint debugPaint;
public SubsamplingScaleImageView(Context context, AttributeSet attr) {
super(context, attr);
setMinimumDpi(160);
setDoubleTapZoomDpi(160);
this.handler = new Handler(new Handler.Callback() {
public boolean handleMessage(Message message) {
if (message.what == MESSAGE_LONG_CLICK && onLongClickListener != null) {
maxTouchCount = 0;
SubsamplingScaleImageView.super.setOnLongClickListener(onLongClickListener);
performLongClick();
SubsamplingScaleImageView.super.setOnLongClickListener(null);
}
return true;
}
});
this.detector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
if (panEnabled && readySent && vTranslate != null && (Math.abs(e1.getX() - e2.getX()) > 50 || Math.abs(e1.getY() - e2.getY()) > 50) && (Math.abs(velocityX) > 500 || Math.abs(velocityY) > 500) && !isZooming) {
PointF vTranslateEnd = new PointF(vTranslate.x + (velocityX * 0.25f), vTranslate.y + (velocityY * 0.25f));
float sCenterXEnd = ((getWidth()/2) - vTranslateEnd.x)/scale;
float sCenterYEnd = ((getHeight()/2) - vTranslateEnd.y)/scale;
new AnimationBuilder(new PointF(sCenterXEnd, sCenterYEnd)).withEasing(EASE_OUT_QUAD).withPanLimited(false).start();
return true;
}
return super.onFling(e1, e2, velocityX, velocityY);
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
performClick();
return true;
}
@Override
public boolean onDoubleTap(MotionEvent e) {
if (zoomEnabled && readySent && vTranslate != null) {
float doubleTapZoomScale = Math.min(maxScale, SubsamplingScaleImageView.this.doubleTapZoomScale);
boolean zoomIn = scale <= doubleTapZoomScale * 0.9;
float targetScale = zoomIn ? doubleTapZoomScale : Math.max(getWidth() / (float) sWidth(), getHeight() / (float) sHeight());
PointF targetSCenter = viewToSourceCoord(new PointF(e.getX(), e.getY()));
if (doubleTapZoomStyle == ZOOM_FOCUS_CENTER_IMMEDIATE) {
setScaleAndCenter(targetScale, targetSCenter);
} else if (doubleTapZoomStyle == ZOOM_FOCUS_CENTER || !zoomIn) {
new AnimationBuilder(targetScale, targetSCenter).withInterruptible(false).start();
} else if (doubleTapZoomStyle == ZOOM_FOCUS_FIXED) {
new AnimationBuilder(targetScale, targetSCenter, new PointF(e.getX(), e.getY())).withInterruptible(false).start();
}
invalidate();
return true;
}
return super.onDoubleTapEvent(e);
}
});
// Handle XML attributes
if (attr != null) {
TypedArray typedAttr = getContext().obtainStyledAttributes(attr, styleable.SubsamplingScaleImageView);
if (typedAttr.hasValue(styleable.SubsamplingScaleImageView_assetName)) {
String assetName = typedAttr.getString(styleable.SubsamplingScaleImageView_assetName);
if (assetName != null && assetName.length() > 0) {
setImageAsset(assetName);
}
}
if (typedAttr.hasValue(styleable.SubsamplingScaleImageView_panEnabled)) {
setPanEnabled(typedAttr.getBoolean(styleable.SubsamplingScaleImageView_panEnabled, true));
}
if (typedAttr.hasValue(styleable.SubsamplingScaleImageView_zoomEnabled)) {
setZoomEnabled(typedAttr.getBoolean(styleable.SubsamplingScaleImageView_zoomEnabled, true));
}
}
}
public SubsamplingScaleImageView(Context context) {
this(context, null);
}
/**
* Sets the image orientation. It's best to call this before setting the image file or asset, because it may waste
* loading of tiles. However, this can be freely called at any time.
*/
public final void setOrientation(int orientation) {
if (!VALID_ORIENTATIONS.contains(orientation)) {
throw new IllegalArgumentException("Invalid orientation: " + orientation);
}
this.orientation = orientation;
reset(false);
invalidate();
requestLayout();
}
/**
* Display an image from a file in internal or external storage.
* @param extFile URI of the file to display.
*/
public final void setImageFile(String extFile) {
reset(true);
BitmapInitTask task = new BitmapInitTask(this, getContext(), extFile, false);
task.execute();
invalidate();
}
/**
* Display an image from a file in internal or external storage, starting with a given orientation setting, scale
* and center. This is the best method to use when you want scale and center to be restored after screen orientation
* change; it avoids any redundant loading of tiles in the wrong orientation.
* @param extFile URI of the file to display.
* @param state State to be restored. Nullable.
*/
public final void setImageFile(String extFile, ImageViewState state) {
reset(true);
restoreState(state);
BitmapInitTask task = new BitmapInitTask(this, getContext(), extFile, false);
task.execute();
invalidate();
}
/**
* Display an image from a file in assets.
* @param assetName asset name.
*/
public final void setImageAsset(String assetName) {
setImageAsset(assetName, null);
}
/**
* Display an image from a file in assets, starting with a given orientation setting, scale and center. This is the
* best method to use when you want scale and center to be restored after screen orientation change; it avoids any
* redundant loading of tiles in the wrong orientation.
* @param assetName asset name.
* @param state State to be restored. Nullable.
*/
public final void setImageAsset(String assetName, ImageViewState state) {
reset(true);
restoreState(state);
BitmapInitTask task = new BitmapInitTask(this, getContext(), assetName, true);
task.execute();
invalidate();
}
/**
* Reset all state before setting/changing image or setting new rotation.
*/
private void reset(boolean newImage) {
scale = 0f;
scaleStart = 0f;
vTranslate = null;
vTranslateStart = null;
pendingScale = 0f;
sPendingCenter = null;
sRequestedCenter = null;
isZooming = false;
isPanning = false;
maxTouchCount = 0;
fullImageSampleSize = 0;
vCenterStart = null;
vDistStart = 0;
anim = null;
if (newImage) {
if (decoder != null) {
synchronized (decoderLock) {
decoder.recycle();
decoder = null;
}
}
sWidth = 0;
sHeight = 0;
sOrientation = 0;
readySent = false;
}
if (tileMap != null) {
for (Map.Entry<Integer, List<Tile>> tileMapEntry : tileMap.entrySet()) {
for (Tile tile : tileMapEntry.getValue()) {
tile.visible = false;
if (tile.bitmap != null) {
tile.bitmap.recycle();
tile.bitmap = null;
}
}
}
tileMap = null;
}
}
/**
* On resize, preserve center and scale. Various behaviours are possible, override this method to use another.
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (readySent) {
setScaleAndCenter(getScale(), getCenter());
}
}
/**
* Measures the width and height of the view, preserving the aspect ratio of the image displayed if wrap_content is
* used. The image will scale within this box, not resizing the view as it is zoomed.
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
boolean resizeWidth = widthSpecMode != MeasureSpec.EXACTLY;
boolean resizeHeight = heightSpecMode != MeasureSpec.EXACTLY;
int width = parentWidth;
int height = parentHeight;
if (sWidth > 0 && sHeight > 0) {
if (resizeWidth && resizeHeight) {
width = sWidth();
height = sHeight();
} else if (resizeHeight) {
height = (int)((((double)sHeight()/(double)sWidth()) * width));
} else if (resizeWidth) {
width = (int)((((double)sWidth()/(double)sHeight()) * height));
}
}
width = Math.max(width, getSuggestedMinimumWidth());
height = Math.max(height, getSuggestedMinimumHeight());
setMeasuredDimension(width, height);
}
/**
* Handle touch events. One finger pans, and two finger pinch and zoom plus panning.
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
PointF vCenterEnd;
float vDistEnd;
// During non-interruptible anims, ignore all touch events
if (anim != null && !anim.interruptible) {
getParent().requestDisallowInterceptTouchEvent(true);
return true;
} else {
anim = null;
}
// Abort if not ready
if (vTranslate == null) {
return true;
}
// Detect flings, taps and double taps
if (detector == null || detector.onTouchEvent(event)) {
return true;
}
int touchCount = event.getPointerCount();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_1_DOWN:
case MotionEvent.ACTION_POINTER_2_DOWN:
anim = null;
getParent().requestDisallowInterceptTouchEvent(true);
maxTouchCount = Math.max(maxTouchCount, touchCount);
if (touchCount >= 2) {
if (zoomEnabled) {
// Start pinch to zoom. Calculate distance between touch points and center point of the pinch.
float distance = distance(event.getX(0), event.getX(1), event.getY(0), event.getY(1));
scaleStart = scale;
vDistStart = distance;
vTranslateStart = new PointF(vTranslate.x, vTranslate.y);
vCenterStart = new PointF((event.getX(0) + event.getX(1))/2, (event.getY(0) + event.getY(1))/2);
} else {
// Abort all gestures on second touch
maxTouchCount = 0;
}
// Cancel long click timer
handler.removeMessages(MESSAGE_LONG_CLICK);
} else {
// Start one-finger pan
vTranslateStart = new PointF(vTranslate.x, vTranslate.y);
vCenterStart = new PointF(event.getX(), event.getY());
// Start long click timer
handler.sendEmptyMessageDelayed(MESSAGE_LONG_CLICK, 600);
}
return true;
case MotionEvent.ACTION_MOVE:
boolean consumed = false;
if (maxTouchCount > 0) {
if (touchCount >= 2) {
// Calculate new distance between touch points, to scale and pan relative to start values.
vDistEnd = distance(event.getX(0), event.getX(1), event.getY(0), event.getY(1));
vCenterEnd = new PointF((event.getX(0) + event.getX(1))/2, (event.getY(0) + event.getY(1))/2);
if (zoomEnabled && (distance(vCenterStart.x, vCenterEnd.x, vCenterStart.y, vCenterEnd.y) > 5 || Math.abs(vDistEnd - vDistStart) > 5 || isPanning)) {
isZooming = true;
isPanning = true;
consumed = true;
scale = Math.min(maxScale, (vDistEnd / vDistStart) * scaleStart);
if (scale <= minScale()) {
// Minimum scale reached so don't pan. Adjust start settings so any expand will zoom in.
vDistStart = vDistEnd;
scaleStart = minScale();
vCenterStart = vCenterEnd;
vTranslateStart = vTranslate;
} else if (panEnabled) {
// Translate to place the source image coordinate that was at the center of the pinch at the start
// at the center of the pinch now, to give simultaneous pan + zoom.
float vLeftStart = vCenterStart.x - vTranslateStart.x;
float vTopStart = vCenterStart.y - vTranslateStart.y;
float vLeftNow = vLeftStart * (scale/scaleStart);
float vTopNow = vTopStart * (scale/scaleStart);
vTranslate.x = vCenterEnd.x - vLeftNow;
vTranslate.y = vCenterEnd.y - vTopNow;
} else if (sRequestedCenter != null) {
// With a center specified from code, zoom around that point.
vTranslate.x = (getWidth()/2) - (scale * sRequestedCenter.x);
vTranslate.y = (getHeight()/2) - (scale * sRequestedCenter.y);
} else {
// With no requested center, scale around the image center.
vTranslate.x = (getWidth()/2) - (scale * (sWidth()/2));
vTranslate.y = (getHeight()/2) - (scale * (sHeight()/2));
}
fitToBounds(true);
refreshRequiredTiles(false);
}
} else if (!isZooming) {
// One finger pan - translate the image. We do this calculation even with pan disabled so click
// and long click behaviour is preserved.
float dx = Math.abs(event.getX() - vCenterStart.x);
float dy = Math.abs(event.getY() - vCenterStart.y);
if (dx > 5 || dy > 5 || isPanning) {
consumed = true;
vTranslate.x = vTranslateStart.x + (event.getX() - vCenterStart.x);
vTranslate.y = vTranslateStart.y + (event.getY() - vCenterStart.y);
float lastX = vTranslate.x;
float lastY = vTranslate.y;
fitToBounds(true);
if (lastX == vTranslate.x || (lastY == vTranslate.y && dy > 10) || isPanning) {
isPanning = true;
} else if (dx > 5) {
// Haven't panned the image, and we're at the left or right edge. Switch to page swipe.
maxTouchCount = 0;
handler.removeMessages(MESSAGE_LONG_CLICK);
getParent().requestDisallowInterceptTouchEvent(false);
}
if (!panEnabled) {
vTranslate.x = vTranslateStart.x;
vTranslate.y = vTranslateStart.y;
getParent().requestDisallowInterceptTouchEvent(false);
}
refreshRequiredTiles(false);
}
}
}
if (consumed) {
handler.removeMessages(MESSAGE_LONG_CLICK);
invalidate();
return true;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_POINTER_2_UP:
handler.removeMessages(MESSAGE_LONG_CLICK);
if (maxTouchCount > 0 && (isZooming || isPanning)) {
if (isZooming && touchCount == 2) {
// Convert from zoom to pan with remaining touch
isPanning = true;
vTranslateStart = new PointF(vTranslate.x, vTranslate.y);
if (event.getActionIndex() == 1) {
vCenterStart = new PointF(event.getX(0), event.getY(0));
} else {
vCenterStart = new PointF(event.getX(1), event.getY(1));
}
}
if (touchCount < 3) {
// End zooming when only one touch point
isZooming = false;
}
if (touchCount < 2) {
// End panning when no touch points
isPanning = false;
maxTouchCount = 0;
}
// Trigger load of tiles now required
refreshRequiredTiles(true);
return true;
}
if (touchCount == 1) {
isZooming = false;
isPanning = false;
maxTouchCount = 0;
}
return true;
}
return super.onTouchEvent(event);
}
@Override
public void setOnLongClickListener(OnLongClickListener onLongClickListener) {
this.onLongClickListener = onLongClickListener;
}
/**
* Draw method should not be called until the view has dimensions so the first calls are used as triggers to calculate
* the scaling and tiling required. Once the view is setup, tiles are displayed as they are loaded.
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
createPaints();
// If image or view dimensions are not known yet, abort.
if (sWidth == 0 || sHeight == 0 || decoder == null || getWidth() == 0 || getHeight() == 0) {
return;
}
// On first render with no tile map ready, initialise it and kick off async base image loading.
if (tileMap == null) {
initialiseBaseLayer(getMaxBitmapDimensions(canvas));
return;
}
// If waiting to translate to new center position, set translate now
if (sPendingCenter != null && pendingScale != null) {
scale = pendingScale;
vTranslate.x = (getWidth()/2) - (scale * sPendingCenter.x);
vTranslate.y = (getHeight()/2) - (scale * sPendingCenter.y);
sPendingCenter = null;
pendingScale = null;
fitToBounds(true);
refreshRequiredTiles(true);
}
// On first display of base image set up position, and in other cases make sure scale is correct.
fitToBounds(false);
// Everything is set up and coordinates are valid. Inform subclasses.
if (!readySent) {
readySent = true;
new Thread(new Runnable() {
public void run() {
onImageReady();
}
}).start();
}
// If animating scale, calculate current scale and center with easing equations
if (anim != null) {
long scaleElapsed = System.currentTimeMillis() - anim.time;
boolean finished = scaleElapsed > anim.duration;
scaleElapsed = Math.min(scaleElapsed, anim.duration);
scale = ease(anim.easing, scaleElapsed, anim.scaleStart, anim.scaleEnd - anim.scaleStart, anim.duration);
// Apply required animation to the focal point
float vFocusNowX = ease(anim.easing, scaleElapsed, anim.vFocusStart.x, anim.vFocusEnd.x - anim.vFocusStart.x, anim.duration);
float vFocusNowY = ease(anim.easing, scaleElapsed, anim.vFocusStart.y, anim.vFocusEnd.y - anim.vFocusStart.y, anim.duration);
// Find out where the focal point is at this scale and adjust its position to follow the animation path
PointF vFocus = sourceToViewCoord(anim.sCenterEnd);
vTranslate.x -= vFocus.x - vFocusNowX;
vTranslate.y -= vFocus.y - vFocusNowY;
// For translate anims, showing the image non-centered is never allowed, for scaling anims it is during the animation.
fitToBounds(finished || (anim.scaleStart == anim.scaleEnd));
refreshRequiredTiles(finished);
if (finished) {
anim = null;
}
invalidate();
}
// Optimum sample size for current scale
int sampleSize = Math.min(fullImageSampleSize, calculateInSampleSize());
// First check for missing tiles - if there are any we need the base layer underneath to avoid gaps
boolean hasMissingTiles = false;
for (Map.Entry<Integer, List<Tile>> tileMapEntry : tileMap.entrySet()) {
if (tileMapEntry.getKey() == sampleSize) {
for (Tile tile : tileMapEntry.getValue()) {
if (tile.visible && (tile.loading || tile.bitmap == null)) {
hasMissingTiles = true;
}
}
}
}
// Render all loaded tiles. LinkedHashMap used for bottom up rendering - lower res tiles underneath.
for (Map.Entry<Integer, List<Tile>> tileMapEntry : tileMap.entrySet()) {
if (tileMapEntry.getKey() == sampleSize || hasMissingTiles) {
for (Tile tile : tileMapEntry.getValue()) {
Rect vRect = convertRect(sourceToViewRect(tile.sRect));
if (!tile.loading && tile.bitmap != null) {
canvas.drawBitmap(tile.bitmap, null, vRect, bitmapPaint);
if (debug) {
canvas.drawRect(vRect, debugPaint);
}
} else if (tile.loading && debug) {
canvas.drawText("LOADING", vRect.left + 5, vRect.top + 35, debugPaint);
}
if (tile.visible && debug) {
canvas.drawText("ISS " + tile.sampleSize + " RECT " + tile.sRect.top + "," + tile.sRect.left + "," + tile.sRect.bottom + "," + tile.sRect.right, vRect.left + 5, vRect.top + 15, debugPaint);
}
}
}
}
if (debug) {
canvas.drawText("Scale: " + String.format("%.2f", scale), 5, 15, debugPaint);
canvas.drawText("Translate: " + String.format("%.2f", vTranslate.x) + ":" + String.format("%.2f", vTranslate.y), 5, 35, debugPaint);
PointF center = getCenter();
canvas.drawText("Source center: " + String.format("%.2f", center.x) + ":" + String.format("%.2f", center.y), 5, 55, debugPaint);
if (anim != null) {
PointF vCenterStart = sourceToViewCoord(anim.sCenterStart);
PointF vCenterEndRequested = sourceToViewCoord(anim.sCenterEndRequested);
PointF vCenterEnd = sourceToViewCoord(anim.sCenterEnd);
canvas.drawCircle(vCenterStart.x, vCenterStart.y, 10, debugPaint);
canvas.drawCircle(vCenterEndRequested.x, vCenterEndRequested.y, 20, debugPaint);
canvas.drawCircle(vCenterEnd.x, vCenterEnd.y, 25, debugPaint);
canvas.drawCircle(getWidth()/2, getHeight()/2, 30, debugPaint);
}
}
}
/**
* Creates Paint objects once when first needed.
*/
private void createPaints() {
if (bitmapPaint == null) {
bitmapPaint = new Paint();
bitmapPaint.setAntiAlias(true);
bitmapPaint.setFilterBitmap(true);
bitmapPaint.setDither(true);
}
if (debugPaint == null && debug) {
debugPaint = new Paint();
debugPaint.setTextSize(18);
debugPaint.setColor(Color.MAGENTA);
debugPaint.setStyle(Style.STROKE);
}
}
/**
* Called on first draw when the view has dimensions. Calculates the initial sample size and starts async loading of
* the base layer image - the whole source subsampled as necessary.
*/
private synchronized void initialiseBaseLayer(Point maxTileDimensions) {
fitToBounds(true);
fullImageSampleSize = calculateInSampleSize();
// Load double resolution - next level will be split into four tiles and at the center all four are required,
// so don't bother with tiling until the next level 16 tiles are needed.
if (fullImageSampleSize > 1) {
fullImageSampleSize /= 2;
}
initialiseTileMap(maxTileDimensions);
List<Tile> baseGrid = tileMap.get(fullImageSampleSize);
for (Tile baseTile : baseGrid) {
BitmapTileTask task = new BitmapTileTask(this, decoder, decoderLock, baseTile);
task.execute();
}
}
/**
* Loads the optimum tiles for display at the current scale and translate, so the screen can be filled with tiles
* that are at least as high resolution as the screen. Frees up bitmaps that are now off the screen.
* @param load Whether to load the new tiles needed. Use false while scrolling/panning for performance.
*/
private void refreshRequiredTiles(boolean load) {
int sampleSize = Math.min(fullImageSampleSize, calculateInSampleSize());
RectF vVisRect = new RectF(0, 0, getWidth(), getHeight());
RectF sVisRect = viewToSourceRect(vVisRect);
// Load tiles of the correct sample size that are on screen. Discard tiles off screen, and those that are higher
// resolution than required, or lower res than required but not the base layer, so the base layer is always present.
for (Map.Entry<Integer, List<Tile>> tileMapEntry : tileMap.entrySet()) {
for (Tile tile : tileMapEntry.getValue()) {
if (tile.sampleSize < sampleSize || (tile.sampleSize > sampleSize && tile.sampleSize != fullImageSampleSize)) {
tile.visible = false;
if (tile.bitmap != null) {
tile.bitmap.recycle();
tile.bitmap = null;
}
}
if (tile.sampleSize == sampleSize) {
if (RectF.intersects(sVisRect, convertRect(tile.sRect))) {
tile.visible = true;
if (!tile.loading && tile.bitmap == null && load) {
BitmapTileTask task = new BitmapTileTask(this, decoder, decoderLock, tile);
task.execute();
}
} else if (tile.sampleSize != fullImageSampleSize) {
tile.visible = false;
if (tile.bitmap != null) {
tile.bitmap.recycle();
tile.bitmap = null;
}
}
} else if (tile.sampleSize == fullImageSampleSize) {
tile.visible = true;
}
}
}
}
/**
* Calculates sample size to fit the source image in given bounds.
*/
private int calculateInSampleSize() {
float adjustedScale = scale;
if (minimumTileDpi > 0) {
DisplayMetrics metrics = getResources().getDisplayMetrics();
float averageDpi = (metrics.xdpi + metrics.ydpi)/2;
adjustedScale = (minimumTileDpi/averageDpi) * scale;
}
int reqWidth = (int)(sWidth() * adjustedScale);
int reqHeight = (int)(sHeight() * adjustedScale);
// Raw height and width of image
int inSampleSize = 1;
if (reqWidth == 0 || reqHeight == 0) {
return 32;
}
if (sHeight() > reqHeight || sWidth() > reqWidth) {
// Calculate ratios of height and width to requested height and width
final int heightRatio = Math.round((float) sHeight() / (float) reqHeight);
final int widthRatio = Math.round((float) sWidth() / (float) reqWidth);
// Choose the smallest ratio as inSampleSize value, this will guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
// We want the actual sample size that will be used, so round down to nearest power of 2.
int power = 1;
while (power * 2 < inSampleSize) {
power = power * 2;
}
return power;
}
/**
* Adjusts hypothetical future scale and translate values to keep scale within the allowed range and the image on screen. Minimum scale
* is set so one dimension fills the view and the image is centered on the other dimension. Used to calculate what the target of an
* animation should be.
* @param center Whether the image should be centered in the dimension it's too small to fill. While animating this can be false to avoid changes in direction as bounds are reached.
* @param scaleAndTranslate The scale we want and the translation we're aiming for. The values are adjusted to be valid.
*/
private void fitToBounds(boolean center, ScaleAndTranslate scaleAndTranslate) {
if (panLimit == PAN_LIMIT_OUTSIDE && isImageReady()) {
center = false;
}
PointF vTranslate = scaleAndTranslate.translate;
float scale = limitedScale(scaleAndTranslate.scale);
float scaleWidth = scale * sWidth();
float scaleHeight = scale * sHeight();
if (panLimit == PAN_LIMIT_CUSTOM && isImageReady()) {
vTranslate.x = Math.max(vTranslate.x, getWidth() - scaleWidth);
vTranslate.y = Math.max(vTranslate.y, 9*getHeight()/10 - scaleHeight);
} else if (center) {
vTranslate.x = Math.max(vTranslate.x, getWidth() - scaleWidth);
vTranslate.y = Math.max(vTranslate.y, getHeight() - scaleHeight);
} else {
vTranslate.x = Math.max(vTranslate.x, -scaleWidth);
vTranslate.y = Math.max(vTranslate.y, -scaleHeight);
}
float maxTx;
float maxTy;
if (panLimit == PAN_LIMIT_CUSTOM && isImageReady()) {
maxTx = Math.max(0, 0);
maxTy = Math.max(0, getHeight()/10);
} else if (center) {
maxTx = Math.max(0, (getWidth() - scaleWidth) / 2);
maxTy = Math.max(0, (getHeight() - scaleHeight) / 2);
} else {
maxTx = Math.max(0, getWidth());
maxTy = Math.max(0, getHeight());
}
vTranslate.x = Math.min(vTranslate.x, maxTx);
vTranslate.y = Math.min(vTranslate.y, maxTy);
scaleAndTranslate.scale = scale;
}
/**
* Adjusts current scale and translate values to keep scale within the allowed range and the image on screen. Minimum scale
* is set so one dimension fills the view and the image is centered on the other dimension.
* @param center Whether the image should be centered in the dimension it's too small to fill. While animating this can be false to avoid changes in direction as bounds are reached.
*/
private void fitToBounds(boolean center) {
if (vTranslate == null) {
vTranslate = new PointF(0, 0);
}
ScaleAndTranslate input = new ScaleAndTranslate(scale, vTranslate);
fitToBounds(center, input);
scale = input.scale;
}
/**
* Once source image and view dimensions are known, creates a map of sample size to tile grid.
*/
private void initialiseTileMap(Point maxTileDimensions) {
this.tileMap = new LinkedHashMap<Integer, List<Tile>>();
int sampleSize = fullImageSampleSize;
int xTiles = 1;
int yTiles = 1;
while (true) {
int sTileWidth = sWidth()/xTiles;
int sTileHeight = sHeight()/yTiles;
int subTileWidth = sTileWidth/sampleSize;
int subTileHeight = sTileHeight/sampleSize;
while (subTileWidth > maxTileDimensions.x || (subTileWidth > getWidth() * 1.25 && sampleSize < fullImageSampleSize)) {
xTiles += 1;
sTileWidth = sWidth()/xTiles;
subTileWidth = sTileWidth/sampleSize;
}
while (subTileHeight > maxTileDimensions.y || (subTileHeight > getHeight() * 1.25 && sampleSize < fullImageSampleSize)) {
yTiles += 1;
sTileHeight = sHeight()/yTiles;
subTileHeight = sTileHeight/sampleSize;
}
List<Tile> tileGrid = new ArrayList<Tile>(xTiles * yTiles);
for (int x = 0; x < xTiles; x++) {
for (int y = 0; y < yTiles; y++) {
Tile tile = new Tile();
tile.sampleSize = sampleSize;
tile.visible = sampleSize == fullImageSampleSize;
tile.sRect = new Rect(
x * sTileWidth,
y * sTileHeight,
(x + 1) * sTileWidth,
(y + 1) * sTileHeight
);
tileGrid.add(tile);
}
}
tileMap.put(sampleSize, tileGrid);
if (sampleSize == 1) {
break;
} else {
sampleSize /= 2;
}
}
}
/**
* Called by worker task when decoder is ready and image size and EXIF orientation is known.
*/
private void onImageInited(BitmapRegionDecoder decoder, int sWidth, int sHeight, int sOrientation) {
this.decoder = decoder;
this.sWidth = sWidth;
this.sHeight = sHeight;
this.sOrientation = sOrientation;
requestLayout();
invalidate();
}
/**
* Called by worker task when a tile has loaded. Redraws the view.
*/
private void onTileLoaded() {
invalidate();
}
/**
* Async task used to get image details without blocking the UI thread.
*/
private static class BitmapInitTask extends AsyncTask<Void, Void, int[]> {
private final WeakReference<SubsamplingScaleImageView> viewRef;
private final WeakReference<Context> contextRef;
private final String source;
private final boolean sourceIsAsset;
private BitmapRegionDecoder decoder;
public BitmapInitTask(SubsamplingScaleImageView view, Context context, String source, boolean sourceIsAsset) {
this.viewRef = new WeakReference<SubsamplingScaleImageView>(view);
this.contextRef = new WeakReference<Context>(context);
this.source = source;
this.sourceIsAsset = sourceIsAsset;
}
@Override
protected int[] doInBackground(Void... params) {
try {
if (viewRef != null && contextRef != null) {
Context context = contextRef.get();
if (context != null) {
int exifOrientation = ORIENTATION_0;
if (sourceIsAsset) {
decoder = BitmapRegionDecoder.newInstance(context.getAssets().open(source, AssetManager.ACCESS_RANDOM), true);
} else {
decoder = BitmapRegionDecoder.newInstance(source, true);
try {
ExifInterface exifInterface = new ExifInterface(source);
int orientationAttr = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
if (orientationAttr == ExifInterface.ORIENTATION_NORMAL) {
exifOrientation = ORIENTATION_0;
} else if (orientationAttr == ExifInterface.ORIENTATION_ROTATE_90) {
exifOrientation = ORIENTATION_90;
} else if (orientationAttr == ExifInterface.ORIENTATION_ROTATE_180) {
exifOrientation = ORIENTATION_180;
} else if (orientationAttr == ExifInterface.ORIENTATION_ROTATE_270) {
exifOrientation = ORIENTATION_270;
} else {
Log.w(TAG, "Unsupported EXIF orientation: " + orientationAttr);
}
} catch (Exception e) {
Log.w(TAG, "Could not get EXIF orientation of image");
}
}
return new int[] { decoder.getWidth(), decoder.getHeight(), exifOrientation };
}
}
} catch (Exception e) {
Log.e(TAG, "Failed to initialise bitmap decoder", e);
}
return null;
}
@Override
protected void onPostExecute(int[] xyo) {
if (viewRef != null && decoder != null) {
final SubsamplingScaleImageView subsamplingScaleImageView = viewRef.get();
if (subsamplingScaleImageView != null && decoder != null && xyo != null && xyo.length == 3) {
subsamplingScaleImageView.onImageInited(decoder, xyo[0], xyo[1], xyo[2]);
}
}
}
}
/**
* Async task used to load images without blocking the UI thread.
*/
private static class BitmapTileTask extends AsyncTask<Void, Void, Bitmap> {
private final WeakReference<SubsamplingScaleImageView> viewRef;
private final WeakReference<BitmapRegionDecoder> decoderRef;
private final WeakReference<Object> decoderLockRef;
private final WeakReference<Tile> tileRef;
public BitmapTileTask(SubsamplingScaleImageView view, BitmapRegionDecoder decoder, Object decoderLock, Tile tile) {
this.viewRef = new WeakReference<SubsamplingScaleImageView>(view);
this.decoderRef = new WeakReference<BitmapRegionDecoder>(decoder);
this.decoderLockRef = new WeakReference<Object>(decoderLock);
this.tileRef = new WeakReference<Tile>(tile);
tile.loading = true;
}
@Override
protected Bitmap doInBackground(Void... params) {
try {
if (decoderRef != null && tileRef != null && viewRef != null) {
final BitmapRegionDecoder decoder = decoderRef.get();
final Object decoderLock = decoderLockRef.get();
final Tile tile = tileRef.get();
final SubsamplingScaleImageView view = viewRef.get();
if (decoder != null && decoderLock != null && tile != null && view != null && !decoder.isRecycled()) {
synchronized (decoderLock) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = tile.sampleSize;
options.inPreferredConfig = Config.RGB_565;
options.inDither = true;
Bitmap bitmap = decoder.decodeRegion(view.fileSRect(tile.sRect), options);
int rotation = view.getRequiredRotation();
if (rotation != 0) {
Matrix matrix = new Matrix();
matrix.postRotate(rotation);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
return bitmap;
}
} else if (tile != null) {
tile.loading = false;
}
}
} catch (Exception e) {
Log.e(TAG, "Failed to decode tile", e);
}
return null;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if (viewRef != null && tileRef != null && bitmap != null) {
final SubsamplingScaleImageView subsamplingScaleImageView = viewRef.get();
final Tile tile = tileRef.get();
if (subsamplingScaleImageView != null && tile != null) {
tile.bitmap = bitmap;
tile.loading = false;
subsamplingScaleImageView.onTileLoaded();
}
}
}
}
private static class Tile {
private Rect sRect;
private int sampleSize;
private Bitmap bitmap;
private boolean loading;
private boolean visible;
}
private static class Anim {
private float scaleStart; // Scale at start of anim
private float scaleEnd; // Scale at end of anim (target)
private PointF sCenterStart; // Source center point at start
private PointF sCenterEnd; // Source center point at end, adjusted for pan limits
private PointF sCenterEndRequested; // Source center point that was requested, without adjustment
private PointF vFocusStart; // View point that was double tapped
private PointF vFocusEnd; // Where the view focal point should be moved to during the anim
private long duration = 500; // How long the anim takes
private boolean interruptible = true; // Whether the anim can be interrupted by a touch
private int easing = EASE_IN_OUT_QUAD; // Easing style
private long time = System.currentTimeMillis(); // Start time
}
private static class ScaleAndTranslate {
private ScaleAndTranslate(float scale, PointF translate) {
this.scale = scale;
this.translate = translate;
}
private float scale;
private PointF translate;
}
/**
* Set scale, center and orientation from saved state.
*/
private void restoreState(ImageViewState state) {
if (state != null && state.getCenter() != null && VALID_ORIENTATIONS.contains(state.getOrientation())) {
this.orientation = state.getOrientation();
this.pendingScale = state.getScale();
this.sPendingCenter = state.getCenter();
invalidate();
}
}
/**
* In SDK 14 and above, use canvas max bitmap width and height instead of the default 2048, to avoid redundant tiling.
*/
private Point getMaxBitmapDimensions(Canvas canvas) {
if (VERSION.SDK_INT >= 14) {
try {
int maxWidth = (Integer)Canvas.class.getMethod("getMaximumBitmapWidth").invoke(canvas);
int maxHeight = (Integer)Canvas.class.getMethod("getMaximumBitmapHeight").invoke(canvas);
return new Point(maxWidth, maxHeight);
} catch (Exception e) {
// Return default
}
}
return new Point(2048, 2048);
}
/**
* Get source width taking rotation into account.
*/
private int sWidth() {
int rotation = getRequiredRotation();
if (rotation == 90 || rotation == 270) {
return sHeight;
} else {
return sWidth;
}
}
/**
* Get source height taking rotation into account.
*/
private int sHeight() {
int rotation = getRequiredRotation();
if (rotation == 90 || rotation == 270) {
return sWidth;
} else {
return sHeight;
}
}
/**
* Converts source rectangle from tile, which treats the image file as if it were in the correct orientation already,
* to the rectangle of the image that needs to be loaded.
*/
private Rect fileSRect(Rect sRect) {
if (getRequiredRotation() == 0) {
return sRect;
} else if (getRequiredRotation() == 90) {
return new Rect(sRect.top, sHeight - sRect.right, sRect.bottom, sHeight - sRect.left);
} else if (getRequiredRotation() == 180) {
return new Rect(sWidth - sRect.right, sHeight - sRect.bottom, sWidth - sRect.left, sHeight - sRect.top);
} else {
return new Rect(sWidth - sRect.bottom, sRect.left, sWidth - sRect.top, sRect.right);
}
}
/**
* Determines the rotation to be applied to tiles, based on EXIF orientation or chosen setting.
*/
private int getRequiredRotation() {
if (orientation == ORIENTATION_USE_EXIF) {
return sOrientation;
} else {
return orientation;
}
}
/**
* Pythagoras distance between two points.
*/
private float distance(float x0, float x1, float y0, float y1) {
float x = x0 - x1;
float y = y0 - y1;
return (float)Math.sqrt(x * x + y * y);
}
/**
* Convert screen coordinate to source coordinate.
*/
public final PointF viewToSourceCoord(PointF vxy) {
return viewToSourceCoord(vxy.x, vxy.y);
}
/**
* Convert screen coordinate to source coordinate.
*/
public final PointF viewToSourceCoord(float vx, float vy) {
if (vTranslate == null) {
return null;
}
float sx = (vx - vTranslate.x)/scale;
float sy = (vy - vTranslate.y)/scale;
return new PointF(sx, sy);
}
/**
* Convert source coordinate to screen coordinate.
*/
public final PointF sourceToViewCoord(PointF sxy) {
return sourceToViewCoord(sxy.x, sxy.y);
}
/**
* Convert source coordinate to screen coordinate.
*/
public final PointF sourceToViewCoord(float sx, float sy) {
if (vTranslate == null) {
return null;
}
float vx = (sx * scale) + vTranslate.x;
float vy = (sy * scale) + vTranslate.y;
return new PointF(vx, vy);
}
/**
* Convert source rect to screen rect.
*/
private RectF sourceToViewRect(Rect sRect) {
return sourceToViewRect(convertRect(sRect));
}
/**
* Convert source rect to screen rect.
*/
private RectF sourceToViewRect(RectF sRect) {
PointF vLT = sourceToViewCoord(new PointF(sRect.left, sRect.top));
PointF vRB = sourceToViewCoord(new PointF(sRect.right, sRect.bottom));
return new RectF(vLT.x, vLT.y, vRB.x, vRB.y);
}
/**
* Convert screen rect to source rect.
*/
private RectF viewToSourceRect(RectF vRect) {
PointF sLT = viewToSourceCoord(new PointF(vRect.left, vRect.top));
PointF sRB = viewToSourceCoord(new PointF(vRect.right, vRect.bottom));
return new RectF(sLT.x, sLT.y, sRB.x, sRB.y);
}
/**
* Int to float rect conversion.
*/
private RectF convertRect(Rect rect) {
return new RectF(rect.left, rect.top, rect.right, rect.bottom);
}
/**
* Float to int rect conversion.
*/
private Rect convertRect(RectF rect) {
return new Rect((int)rect.left, (int)rect.top, (int)rect.right, (int)rect.bottom);
}
/**
* Get the translation required to place a given source coordinate at the center of the screen. Accepts the desired
* scale as an argument, so this is independent of current translate and scale. The result is fitted to bounds, putting
* the image point as near to the screen center as permitted.
*/
private PointF vTranslateForSCenter(PointF sCenter, float scale) {
PointF vTranslate = new PointF((getWidth()/2) - (sCenter.x * scale), (getHeight()/2) - (sCenter.y * scale));
ScaleAndTranslate sat = new ScaleAndTranslate(scale, vTranslate);
fitToBounds(true, sat);
return vTranslate;
}
/**
* Given a requested source center and scale, calculate what the actual center will have to be to keep the image in
* pan limits, keeping the requested center as near to the middle of the screen as allowed.
*/
private PointF limitedSCenter(PointF sCenter, float scale) {
PointF vTranslate = vTranslateForSCenter(sCenter, scale);
int mY = getHeight()/2;
float sx = ((getWidth()/2) - vTranslate.x)/scale;
float sy = ((getHeight()/2) - vTranslate.y)/scale;
return new PointF(sx, sy);
}
/**
* Returns the minimum allowed scale.
*/
private float minScale() {
return Math.min(getWidth() / (float) sWidth(), (getHeight())/ (float) sHeight());
}
/**
* Adjust a requested scale to be within the allowed limits.
*/
private float limitedScale(float targetScale) {
targetScale = Math.max(minScale(), targetScale);
targetScale = Math.min(maxScale, targetScale);
return targetScale;
}
/**
* Apply a selected type of easing.
* @param type Easing type, from static fields
* @param time Elapsed time
* @param from Start value
* @param change Target value
* @param duration Anm duration
* @return Current value
*/
private float ease(int type, long time, float from, float change, long duration) {
switch (type) {
case EASE_IN_OUT_QUAD:
return easeInOutQuad(time, from, change, duration);
case EASE_OUT_QUAD:
return easeOutQuad(time, from, change, duration);
default:
throw new IllegalStateException("Unexpected easing type: " + type);
}
}
/**
* Quadratic easing for fling. With thanks to Robert Penner - http://gizma.com/easing/
* @param time Elapsed time
* @param from Start value
* @param change Target value
* @param duration Anm duration
* @return Current value
*/
private float easeOutQuad(long time, float from, float change, long duration) {
float progress = (float)time/(float)duration;
return -change * progress*(progress-2) + from;
}
/**
* Quadratic easing for scale and center animations. With thanks to Robert Penner - http://gizma.com/easing/
* @param time Elapsed time
* @param from Start value
* @param change Target value
* @param duration Anm duration
* @return Current value
*/
private float easeInOutQuad(long time, float from, float change, long duration) {
float timeF = time/(duration/2f);
if (timeF < 1) {
return (change/2f * timeF * timeF) + from;
} else {
timeF--;
return (-change/2f) * (timeF * (timeF - 2) - 1) + from;
}
}
/**
* Set the pan limiting style. See static fields. Normally {@link #PAN_LIMIT_INSIDE} is best, for image galleries.
*/
public final void setPanLimit(int panLimit) {
if (!VALID_PAN_LIMITS.contains(panLimit)) {
throw new IllegalArgumentException("Invalid pan limit: " + panLimit);
}
this.panLimit = panLimit;
if (isImageReady()) {
fitToBounds(true);
invalidate();
}
}
/**
* Set the maximum scale allowed. A value of 1 means 1:1 pixels at maximum scale. You may wish to set this according
* to screen density - on a retina screen, 1:1 may still be too small. Consider using {@link #setMinimumDpi(int)},
* which is density aware.
*/
public final void setMaxScale(float maxScale) {
this.maxScale = maxScale;
}
/**
* Returns the maximum allowed scale.
*/
public float getMaxScale() {
return maxScale;
}
/**
* This is a screen density aware alternative to {@link #setMaxScale(float)}; it allows you to express the maximum
* allowed scale in terms of the minimum pixel density. This avoids the problem of 1:1 scale still being
* too small on a high density screen. A sensible starting point is 160 - the default used by this view.
* @param dpi Source image pixel density at maximum zoom.
*/
public final void setMinimumDpi(int dpi) {
DisplayMetrics metrics = getResources().getDisplayMetrics();
float averageDpi = (metrics.xdpi + metrics.ydpi)/2;
setMaxScale(averageDpi/dpi);
}
/**
* Returns the minimum allowed scale.
*/
public final float getMinScale() {
return minScale();
}
/**
* By default, image tiles are at least as high resolution as the screen. For a retina screen this may not be
* necessary, and may increase the likelihood of an OutOfMemoryError. This method sets a DPI at which higher
* resolution tiles should be loaded. Using a lower number will on average use less memory but result in a lower
* quality image. 160-240dpi will usually be enough.
* @param minimumTileDpi Tile loading threshold.
*/
public void setMinimumTileDpi(int minimumTileDpi) {
DisplayMetrics metrics = getResources().getDisplayMetrics();
float averageDpi = (metrics.xdpi + metrics.ydpi)/2;
this.minimumTileDpi = (int)Math.min(averageDpi, minimumTileDpi);
if (isImageReady()) {
reset(false);
invalidate();
}
}
/**
* Returns the source point at the center of the view.
*/
public final PointF getCenter() {
int mX = getWidth()/2;
int mY = getHeight()/2;
return viewToSourceCoord(mX, mY);
}
/**
* Returns the current scale value.
*/
public final float getScale() {
return scale;
}
/**
* Externally change the scale and translation of the source image. This may be used with getCenter() and getScale()
* to restore the scale and zoom after a screen rotate.
* @param scale New scale to set.
* @param sCenter New source image coordinate to center on the screen, subject to boundaries.
*/
public final void setScaleAndCenter(float scale, PointF sCenter) {
this.anim = null;
this.pendingScale = scale;
this.sPendingCenter = sCenter;
this.sRequestedCenter = sCenter;
invalidate();
}
/**
* Fully zoom out and return the image to the middle of the screen. This might be useful if you have a view pager
* and want images to be reset when the user has moved to another page.
*/
public final void resetScaleAndCenter() {
this.anim = null;
this.pendingScale = limitedScale(0);
if (isImageReady()) {
this.sPendingCenter = new PointF(sWidth()/2, sHeight()/2);
} else {
this.sPendingCenter = new PointF(0, 0);
}
invalidate();
}
/**
* Subclasses can override this method to be informed when the view is set up and ready for rendering, so they can
* skip their own rendering until the base layer (and its scale and translate) are known.
*/
protected void onImageReady() {
}
/**
* Call to find whether the view is initialised and ready for rendering tiles.
*/
public final boolean isImageReady() {
return readySent && vTranslate != null && tileMap != null && sWidth > 0 && sHeight > 0;
}
/**
* Get source width, ignoring orientation. If {@link #getOrientation()} returns 90 or 270, you can use {@link #getSHeight()}
* for the apparent width.
*/
public final int getSWidth() {
return sWidth;
}
/**
* Get source height, ignoring orientation. If {@link #getOrientation()} returns 90 or 270, you can use {@link #getSWidth()}
* for the apparent height.
*/
public final int getSHeight() {
return sHeight;
}
/**
* Returns the orientation setting. This can return {@link #ORIENTATION_USE_EXIF}, in which case it doesn't tell you
* the applied orientation of the image. For that, use {@link #getAppliedOrientation()}.
*/
public final int getOrientation() {
return orientation;
}
/**
* Returns the actual orientation of the image relative to the source file. This will be based on the source file's
* EXIF orientation if you're using ORIENTATION_USE_EXIF. Values are 0, 90, 180, 270.
*/
public final int getAppliedOrientation() {
return getRequiredRotation();
}
/**
* Get the current state of the view (scale, center, orientation) for restoration after rotate. Will return null if
* the view is not ready.
*/
public final ImageViewState getState() {
if (vTranslate != null && sWidth > 0 && sHeight > 0) {
return new ImageViewState(getScale(), getCenter(), getOrientation());
}
return null;
}
/**
* Returns true if zoom gesture detection is enabled.
*/
public final boolean isZoomEnabled() {
return zoomEnabled;
}
/**
* Enable or disable zoom gesture detection. Disabling zoom locks the the current scale.
*/
public final void setZoomEnabled(boolean zoomEnabled) {
this.zoomEnabled = zoomEnabled;
}
/**
* Returns true if pan gesture detection is enabled.
*/
public final boolean isPanEnabled() {
return panEnabled;
}
/**
* Enable or disable pan gesture detection. Disabling pan causes the image to be centered.
*/
public final void setPanEnabled(boolean panEnabled) {
this.panEnabled = panEnabled;
if (!panEnabled && vTranslate != null) {
vTranslate.x = (getWidth()/2) - (scale * (sWidth()/2));
vTranslate.y = (getHeight()/2) - (scale * (sHeight()/2));
if (isImageReady()) {
refreshRequiredTiles(true);
invalidate();
}
}
}
/**
* Set the scale the image will zoom in to when double tapped. This also the scale point where a double tap is interpreted
* as a zoom out gesture - if the scale is greater than 90% of this value, a double tap zooms out. Avoid using values
* greater than the max zoom.
* @param doubleTapZoomScale New value for double tap gesture zoom scale.
*/
public final void setDoubleTapZoomScale(float doubleTapZoomScale) {
this.doubleTapZoomScale = doubleTapZoomScale;
}
/**
* A density aware alternative to {@link #setDoubleTapZoomScale(float)}; this allows you to express the scale the
* image will zoom in to when double tapped in terms of the image pixel density. Values lower than the max scale will
* be ignored. A sensible starting point is 160 - the default used by this view.
* @param dpi New value for double tap gesture zoom scale.
*/
public final void setDoubleTapZoomDpi(int dpi) {
DisplayMetrics metrics = getResources().getDisplayMetrics();
float averageDpi = (metrics.xdpi + metrics.ydpi)/2;
setDoubleTapZoomScale(averageDpi/dpi);
}
/**
* Set the type of zoom animation to be used for double taps. See static fields.
* @param doubleTapZoomStyle New value for zoom style.
*/
public final void setDoubleTapZoomStyle(int doubleTapZoomStyle) {
if (!VALID_ZOOM_STYLES.contains(doubleTapZoomStyle)) {
throw new IllegalArgumentException("Invalid zoom style: " + doubleTapZoomStyle);
}
this.doubleTapZoomStyle = doubleTapZoomStyle;
}
/**
* Enables visual debugging, showing tile boundaries and sizes.
*/
public final void setDebug(boolean debug) {
this.debug = debug;
}
/**
* Creates a panning animation builder, that when started will animate the image to place the given coordinates of
* the image in the center of the screen. If doing this would move the image beyond the edges of the screen, the
* image is instead animated to move the center point as near to the center of the screen as is allowed - it's
* guaranteed to be on screen.
* @param sCenter Target center point
* @return {@link AnimationBuilder} instance. Call {@link com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView.AnimationBuilder#start()} to start the anim.
*/
public AnimationBuilder animateCenter(PointF sCenter) {
if (!isImageReady()) {
return null;
}
return new AnimationBuilder(sCenter);
}
/**
* Creates a scale animation builder, that when started will animate a zoom in or out. If this would move the image
* beyond the panning limits, the image is automatically panned during the animation.
* @param scale Target scale.
* @return {@link AnimationBuilder} instance. Call {@link com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView.AnimationBuilder#start()} to start the anim.
*/
public AnimationBuilder animateScale(float scale) {
if (!isImageReady()) {
return null;
}
return new AnimationBuilder(scale);
}
/**
* Creates a scale animation builder, that when started will animate a zoom in or out. If this would move the image
* beyond the panning limits, the image is automatically panned during the animation.
* @param scale Target scale.
* @return {@link AnimationBuilder} instance. Call {@link com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView.AnimationBuilder#start()} to start the anim.
*/
public AnimationBuilder animateScaleAndCenter(float scale, PointF sCenter) {
if (!isImageReady()) {
return null;
}
return new AnimationBuilder(scale, sCenter);
}
/**
* Builder class used to set additional options for a scale animation. Create an instance using {@link #animateScale(float)},
* then set your options and call {@link #start()}.
*/
public final class AnimationBuilder {
private final float targetScale;
private final PointF targetSCenter;
private final PointF vFocus;
private long duration = 500;
private int easing = EASE_IN_OUT_QUAD;
private boolean interruptible = true;
private boolean panLimited = true;
private AnimationBuilder(PointF sCenter) {
this.targetScale = scale;
this.targetSCenter = sCenter;
this.vFocus = null;
}
private AnimationBuilder(float scale) {
this.targetScale = scale;
this.targetSCenter = getCenter();
this.vFocus = null;
}
private AnimationBuilder(float scale, PointF sCenter) {
this.targetScale = scale;
this.targetSCenter = sCenter;
this.vFocus = null;
}
private AnimationBuilder(float scale, PointF sCenter, PointF vFocus) {
this.targetScale = scale;
this.targetSCenter = sCenter;
this.vFocus = vFocus;
}
/**
* Desired duration of the anim in milliseconds. Default is 500.
* @param duration duration in milliseconds.
* @return this builder for method chaining.
*/
public AnimationBuilder withDuration(long duration) {
this.duration = duration;
return this;
}
/**
* Whether the animation can be interrupted with a touch. Default is true.
* @param interruptible interruptible flag.
* @return this builder for method chaining.
*/
public AnimationBuilder withInterruptible(boolean interruptible) {
this.interruptible = interruptible;
return this;
}
/**
* Set the easing style. See static fields. {@link #EASE_IN_OUT_QUAD} is recommended, and the default.
* @param easing easing style.
* @return this builder for method chaining.
*/
public AnimationBuilder withEasing(int easing) {
if (!VALID_EASING_STYLES.contains(easing)) {
throw new IllegalArgumentException("Unknown easing type: " + easing);
}
this.easing = easing;
return this;
}
/**
* Only for internal use. When set to true, the animation proceeds towards the actual end point - the nearest
* point to the center allowed by pan limits. When false, animation is in the direction of the requested end
* point and is stopped when the limit for each axis is reached. The latter behaviour is used for flings but
* nothing else.
*/
private AnimationBuilder withPanLimited(boolean panLimited) {
this.panLimited = panLimited;
return this;
}
/**
* Starts the animation.
*/
public void start() {
float targetScale = limitedScale(this.targetScale);
PointF targetSCenter = panLimited ? limitedSCenter(this.targetSCenter, targetScale) : this.targetSCenter;
anim = new Anim();
anim.scaleStart = scale;
anim.scaleEnd = targetScale;
anim.time = System.currentTimeMillis();
anim.sCenterEndRequested = targetSCenter;
anim.sCenterStart = getCenter();
anim.sCenterEnd = targetSCenter;
anim.vFocusStart = sourceToViewCoord(targetSCenter);
anim.vFocusEnd = new PointF(
getWidth()/2,
getHeight()/2
);
anim.duration = duration;
anim.interruptible = interruptible;
anim.easing = easing;
anim.time = System.currentTimeMillis();
if (vFocus != null) {
// Calculate where translation will be at the end of the anim
float vTranslateXEnd = vFocus.x - (targetScale * anim.sCenterStart.x);
float vTranslateYEnd = vFocus.y - (targetScale * anim.sCenterStart.y);
ScaleAndTranslate satEnd = new ScaleAndTranslate(targetScale, new PointF(vTranslateXEnd, vTranslateYEnd));
// Fit the end translation into bounds
fitToBounds(true, satEnd);
// Adjust the position of the focus point at end so image will be in bounds
anim.vFocusEnd = new PointF(
vFocus.x + (satEnd.translate.x - vTranslateXEnd),
vFocus.y + (satEnd.translate.y - vTranslateYEnd)
);
}
invalidate();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:startColor="#20000000"
android:endColor="@android:color/transparent"
android:angle="90" >
</gradient>
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:startColor="#20000000"
android:endColor="@android:color/transparent"
android:angle="270" >
</gradient>
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Drop Shadow Stack -->
<!-- Background -->
<item>
<shape>
<solid android:color="#e5e5e5" />
</shape>
</item>
</layer-list>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#30555555"/>
<corners android:radius="2dp" />
</shape>
</item>
<item
android:left="0dp"
android:right="0dp"
android:top="0dp"
android:bottom="2dp">
<shape android:shape="rectangle">
<solid android:color="#FFFFFF"/>
<corners android:radius="2dp" />
</shape>
</item>
</layer-list>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Drop Shadow Stack -->
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#00999999" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#10999999" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#20999999" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#10999999" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#00999999" />
</shape>
</item>
<!-- Background -->
<item>
<shape>
<solid android:color="@android:color/transparent" />
</shape>
</item>
</layer-list>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Drop Shadow Stack -->
<!-- <item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#00999999" />
<corners android:radius="2dp" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#10999999" />
<corners android:radius="2dp" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#20999999" />
<corners android:radius="2dp" />
</shape>
</item>
<item>
<shape>
<padding android:top="0dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#30999999" />
<corners android:radius="2dp" />
</shape>
</item>
<item>
<shape>
<padding android:top="0dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#20999999" />
<corners android:radius="2dp" />
</shape>
</item>-->
<!-- Background -->
<item>
<shape>
<solid android:color="#F0FFFFFF" />
<!-- <corners android:radius="2dp" />-->
</shape>
</item>
</layer-list>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Drop Shadow Stack -->
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#00999999" />
<corners android:radius="5dp" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#00999999" />
<corners android:radius="5dp" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#00999999" />
<corners android:radius="5dp" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#00999999" />
<corners android:radius="5dp" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#00999999" />
<corners android:radius="5dp" />
</shape>
</item>
<!-- Background -->
<item>
<shape>
<gradient
android:type="linear"
android:centerX="6%"
android:startColor="#FFe4e4e4"
android:centerColor="#FFf6f6f6"
android:endColor="#FFffffff"
android:angle="90"/>
<corners android:radius="5dp" />
</shape>
</item>
</layer-list>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<gradient
android:type="linear"
android:centerX="20%"
android:startColor="#66000000"
android:centerColor="#22000000"
android:endColor="#00f6f6f6"
android:angle="270"/>
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<gradient
android:type="linear"
android:centerX="2%"
android:startColor="#FFe4e4e4"
android:centerColor="#FFf6f6f6"
android:endColor="#FFffffff"
android:angle="90"/>
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<gradient
android:type="linear"
android:centerX="60%"
android:startColor="#00000000"
android:centerColor="#19000000"
android:endColor="#FF000000"
android:angle="270"/>
</shape>
\ No newline at end of file
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path
android:fillType="evenOdd"
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
android:strokeColor="#00000000"
android:strokeWidth="1">
<aapt:attr name="android:fillColor">
<gradient
android:endX="78.5885"
android:endY="90.9159"
android:startX="48.7653"
android:startY="61.0927"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
android:strokeColor="#00000000"
android:strokeWidth="1" />
</vector>
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
tools:context="app.insti.fragment.MapFragment">
<fragment <LinearLayout
android:id="@+id/viewMap"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
map:cameraZoom="18" /> android:orientation="vertical"
android:focusable="true"
<!--TODO: Change colours--> android:focusableInTouchMode="true">
<android.support.design.widget.FloatingActionButton
android:id="@+id/location_button" <android.support.v7.widget.Toolbar
android:layout_width="wrap_content" android:id="@+id/toolbar"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:layout_gravity="bottom|end" android:layout_height="?attr/actionBarSize"
android:layout_marginBottom="48dp" android:background="@color/colorPrimary">
android:layout_marginEnd="@dimen/fab_margin"
android:src="@drawable/ic_my_location_black_24dp" /> <EditText
android:id="@+id/search"
android:layout_width="fill_parent"
android:layout_height="48dp"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:background="@null"
android:dropDownHeight="0dp"
android:fontFamily="sans-serif-light"
android:hint="Search"
android:imeOptions="actionSearch"
android:inputType="textNoSuggestions"
android:paddingBottom="8dp"
android:paddingLeft="8dp"
android:paddingRight="50dp"
android:paddingTop="8dp"
android:selectAllOnFocus="true"
android:singleLine="true" />
<TextView
android:id="@+id/settings_title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:fontFamily="sans-serif-light"
android:paddingLeft="8dp"
android:paddingRight="76dp"
android:text="Settings"
android:visibility="gone" />
<ImageButton
android:id="@+id/index_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentRight="true"
android:background="@android:color/transparent"
android:contentDescription="index"
android:cropToPadding="true"
android:padding="12dp"
android:scaleType="fitXY"
android:src="@drawable/dept_menu" />
<ImageButton
android:id="@+id/map_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentRight="true"
android:background="@android:color/transparent"
android:contentDescription="map"
android:cropToPadding="true"
android:padding="12dp"
android:scaleType="fitXY"
android:src="@drawable/dept_menu_off"
android:visibility="gone" />
<ImageButton
android:id="@+id/remove_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentRight="true"
android:background="@android:color/transparent"
android:contentDescription="remove"
android:padding="8dp"
android:src="@drawable/ic_action_remove"
android:visibility="gone" />
</android.support.v7.widget.Toolbar>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/darker_gray"
tools:context="com.mrane.campusmap.MainActivity"
tools:ignore="MergeRootFrame"
android:focusable="true"
android:focusableInTouchMode="true">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="true"
android:focusableInTouchMode="true"></LinearLayout>
<com.mrane.navigation.SlidingUpPanelLayout xmlns:sothree="http://schemas.android.com/apk/res-auto"
android:id="@+id/sliding_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="bottom">
<!-- MAIN CONTENT -->
<com.mrane.zoomview.CampusMapView
android:id="@+id/campusMapView"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:paddingTop="48dp" />
<!-- SLIDING LAYOUT -->
<include layout="@layout/map_card_layout" />
</com.mrane.navigation.SlidingUpPanelLayout>
<RelativeLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_alignParentTop="true"
android:orientation="vertical"></RelativeLayout>
</RelativeLayout>
</android.support.v4.widget.DrawerLayout>
</LinearLayout>
</FrameLayout> </FrameLayout>
\ No newline at end of file
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MyActivity">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/primary"
app:popupTheme="@style/Theme.AppCompat"
app:theme="@style/ToolbarTheme">
<include layout="@layout/actionbar" />
</android.support.v7.widget.Toolbar>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/darker_gray"
tools:context="com.mrane.campusmap.MainActivity"
tools:ignore="MergeRootFrame">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="true"
android:focusableInTouchMode="true"></LinearLayout>
<com.mrane.navigation.SlidingUpPanelLayout xmlns:sothree="http://schemas.android.com/apk/res-auto"
android:id="@+id/sliding_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="bottom"
sothree:dragView="@+id/dragView"
sothree:panelHeight="0dp"
sothree:paralaxOffset="140dp"
sothree:shadowHeight="4dp">
<!-- MAIN CONTENT -->
<com.mrane.zoomview.CampusMapView
android:id="@+id/campusMapView"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:paddingTop="48dp" />
<!-- SLIDING LAYOUT -->
<include layout="@layout/card_layout" />
</com.mrane.navigation.SlidingUpPanelLayout>
<RelativeLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_alignParentTop="true"
android:orientation="vertical"></RelativeLayout>
</RelativeLayout>
</android.support.v4.widget.DrawerLayout>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MapActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/place_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true" />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/dragView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#eeeeee"
android:clickable="true"
android:focusable="false"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/new_small_card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<ImageView
android:id="@+id/place_color"
android:layout_width="12dp"
android:layout_height="fill_parent" />
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="8dp" >
<ImageButton
android:id="@+id/add_marker_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentTop="true"
android:layout_marginRight="0dp"
android:layout_marginTop="4dp"
android:layout_alignParentRight="true"
android:background="@android:color/transparent"
android:contentDescription="Search"
android:cropToPadding="true"
android:onClick="addMarkerClick"
android:padding="8dp"
android:scaleType="fitXY" />
<TextView
android:id="@+id/place_name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_toLeftOf="@id/add_marker_icon"
android:ellipsize="end"
android:fontFamily="sans_serif"
android:maxLines="1"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:paddingTop="8dp"
android:textSize="8dp" >
</TextView>
<TextView
android:id="@+id/place_sub_head"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@id/place_name"
android:layout_toLeftOf="@id/add_marker_icon"
android:fontFamily="sans_serif_light"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:text="Search"
android:textColor="@color/colorWhite"
android:textSize="18dp" />
</RelativeLayout>
</LinearLayout>
<RelativeLayout
android:id="@+id/new_expand_container"
android:layout_width="match_parent"
android:layout_height="fill_parent">
<com.mrane.navigation.EndDetectScrollView
android:id="@+id/new_expanded_place_card_scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:id="@+id/expanded_place_card"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#e5e5e5"
android:orientation="horizontal" >
</LinearLayout>
<LinearLayout
android:id="@+id/other_details"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:orientation="vertical" >
</LinearLayout>
</RelativeLayout>
</com.mrane.navigation.EndDetectScrollView>
<RelativeLayout
android:id="@+id/color_strip"
android:layout_width="12dp"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" >
<View
android:id="@+id/place_group_color"
android:layout_width="12dp"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="0dp"
android:alpha="0.5"
android:paddingLeft="0dp" />
<View
android:layout_width="12dp"
android:layout_height="20dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="0dp"
android:alpha="0.5"
android:paddingLeft="0dp" />
</RelativeLayout>
<View
android:layout_width="match_parent"
android:layout_height="8dp"
android:layout_alignParentTop="true" />
</RelativeLayout>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/child_name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:minHeight="56dp"
android:textSize="18dp"
android:fontFamily="sans-serif-light" />
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#e0e0e0" >
<LinearLayout
android:id="@+id/header_layout"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:orientation="horizontal">
<ImageView
android:id="@+id/arrow_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:paddingLeft="16dp"
android:paddingRight="8dp"
android:cropToPadding="true"
android:scaleType="centerInside" />
<TextView
android:id="@+id/list_header"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:paddingLeft="8dp" />
</LinearLayout>
<ListView
android:id="@+id/child_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/header_layout"
android:paddingLeft="48dp"
android:background="#e5e5e5"></ListView>
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="56dp"
android:orientation="vertical"
android:background="#F5F5F5" >
<ImageView
android:id="@+id/group_color"
android:layout_width="12dp"
android:layout_height="56dp"
android:layout_alignParentLeft="true"
android:paddingLeft="0dp"
android:layout_marginLeft="0dp"
android:cropToPadding="true"/>
<ImageView
android:id="@+id/icon_expand"
android:layout_width="32dp"
android:layout_height="56dp"
android:layout_toRightOf="@id/group_color"
android:cropToPadding="true"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:contentDescription="list item"
android:visibility="visible" />
<TextView
android:id="@+id/lblListHeader"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="@id/icon_expand"
android:padding="8dp"
android:paddingLeft="?android:attr/expandableListPreferredItemPaddingLeft" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_alignParentBottom="true" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_alignParentTop="true" />
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ExpandableListView
android:id="@+id/index_list"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:divider="@null"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:groupIndicator="@null"
android:background="@android:color/transparent"
android:transcriptMode="disabled" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView
android:id="@+id/suggestion_list"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:paddingLeft="16dp"
android:paddingRight="16dp" >
</ListView>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="48dp"
android:orientation="horizontal"
android:background="#F0E5E5E5">
<RelativeLayout
android:layout_width="12dp"
android:layout_height="fill_parent">
<View
android:id="@+id/item_group_color"
android:layout_width="12dp"
android:layout_height="fill_parent"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:paddingLeft="0dp"
android:layout_marginLeft="0dp"/>
<View
android:layout_width="12dp"
android:layout_height="fill_parent"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:paddingLeft="0dp"
android:layout_marginLeft="0dp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:minHeight="48dp"
android:paddingRight="8dp">
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:padding="8dp"
android:layout_marginLeft="40dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true" />
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:padding="8dp"
android:layout_marginLeft="40dp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true" />
<TextView
android:id="@+id/lblListItem"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:padding="8dp"
android:fontFamily="sans-serif-light"
android:layout_marginLeft="48dp" />
</RelativeLayout>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="12dp" >
<TextView
android:id="@+id/desc_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:paddingBottom="0dp"
android:textSize="20sp" />
<TextView
android:id="@+id/desc_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/desc_header"
android:lineSpacingExtra="3dp"
android:padding="8dp"
android:textSize="18sp"
android:paddingTop="0dp"
android:textIsSelectable="true"/>
<View
android:layout_below="@id/desc_content"
android:layout_width="match_parent"
android:layout_height="96dp"/>
<View
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true" />
<View
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true" />
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/row_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
android:fontFamily="sans-serif-light" >
</TextView>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2014 David Morrissey
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.
-->
<resources>
<declare-styleable name="SubsamplingScaleImageView">
<attr name="assetName" format="string" />
<attr name="panEnabled" format="boolean" />
<attr name="zoomEnabled" format="boolean" />
</declare-styleable>
<declare-styleable name="SlidingUpPanelLayout">
<attr name="panelHeight" format="dimension" />
<attr name="shadowHeight" format="dimension" />
<attr name="paralaxOffset" format="dimension" />
<attr name="fadeColor" format="color" />
<attr name="flingVelocity" format="integer" />
<attr name="dragView" format="reference" />
<attr name="overlay" format="boolean" />
<attr name="anchorPoint" format="float" />
<attr name="initialState" format="enum">
<enum name="expanded" value="0" />
<enum name="collapsed" value="1" />
<enum name="anchored" value="2" />
<enum name="hidden" value="3" />
</attr>
</declare-styleable>
</resources>
\ No newline at end of file
...@@ -7,4 +7,9 @@ ...@@ -7,4 +7,9 @@
<dimen name="fab_margin">16dp</dimen> <dimen name="fab_margin">16dp</dimen>
<dimen name="quick_links_size">18sp</dimen> <dimen name="quick_links_size">18sp</dimen>
<dimen name="links_margin_start">8dp</dimen> <dimen name="links_margin_start">8dp</dimen>
<!-- Map -->
<dimen name="card_height">360dp</dimen>
<dimen name="hidden_card_height">80dp</dimen>
<dimen name="expanded_card_height">280dp</dimen>
</resources> </resources>
...@@ -36,4 +36,7 @@ ...@@ -36,4 +36,7 @@
<item>Tansa House</item> <item>Tansa House</item>
<item>QIP</item> <item>QIP</item>
</string-array> </string-array>
<string name="drawer_open">Open the drawer</string>
<string name="drawer_close">Close the drawer</string>
</resources> </resources>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment