1 /** 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 package com.android.launcher3.util; 17 18 19 import android.text.TextUtils; 20 import android.util.Pair; 21 import android.util.Xml; 22 23 import org.xmlpull.v1.XmlSerializer; 24 25 import java.io.IOException; 26 import java.io.StringWriter; 27 import java.io.Writer; 28 import java.util.ArrayList; 29 import java.util.HashMap; 30 import java.util.Map; 31 32 /** 33 * Helper class to build xml for Launcher Layout 34 */ 35 public class LauncherLayoutBuilder { 36 37 // Object Tags 38 private static final String TAG_WORKSPACE = "workspace"; 39 private static final String TAG_AUTO_INSTALL = "autoinstall"; 40 private static final String TAG_FOLDER = "folder"; 41 private static final String TAG_APPWIDGET = "appwidget"; 42 private static final String TAG_EXTRA = "extra"; 43 44 private static final String ATTR_CONTAINER = "container"; 45 private static final String ATTR_RANK = "rank"; 46 47 private static final String ATTR_PACKAGE_NAME = "packageName"; 48 private static final String ATTR_CLASS_NAME = "className"; 49 private static final String ATTR_TITLE = "title"; 50 private static final String ATTR_SCREEN = "screen"; 51 52 // x and y can be specified as negative integers, in which case -1 represents the 53 // last row / column, -2 represents the second last, and so on. 54 private static final String ATTR_X = "x"; 55 private static final String ATTR_Y = "y"; 56 private static final String ATTR_SPAN_X = "spanX"; 57 private static final String ATTR_SPAN_Y = "spanY"; 58 59 private static final String ATTR_CHILDREN = "children"; 60 61 62 // Style attrs -- "Extra" 63 private static final String ATTR_KEY = "key"; 64 private static final String ATTR_VALUE = "value"; 65 66 private static final String CONTAINER_DESKTOP = "desktop"; 67 private static final String CONTAINER_HOTSEAT = "hotseat"; 68 69 private final ArrayList<Pair<String, HashMap<String, Object>>> mNodes = new ArrayList<>(); 70 atHotseat(int rank)71 public Location atHotseat(int rank) { 72 Location l = new Location(); 73 l.items.put(ATTR_CONTAINER, CONTAINER_HOTSEAT); 74 l.items.put(ATTR_RANK, Integer.toString(rank)); 75 return l; 76 } 77 atWorkspace(int x, int y, int screen)78 public Location atWorkspace(int x, int y, int screen) { 79 Location l = new Location(); 80 l.items.put(ATTR_CONTAINER, CONTAINER_DESKTOP); 81 l.items.put(ATTR_X, Integer.toString(x)); 82 l.items.put(ATTR_Y, Integer.toString(y)); 83 l.items.put(ATTR_SCREEN, Integer.toString(screen)); 84 return l; 85 } 86 build()87 public String build() throws IOException { 88 StringWriter writer = new StringWriter(); 89 build(writer); 90 return writer.toString(); 91 } 92 build(Writer writer)93 public void build(Writer writer) throws IOException { 94 XmlSerializer serializer = Xml.newSerializer(); 95 serializer.setOutput(writer); 96 97 serializer.startDocument("UTF-8", true); 98 serializer.startTag(null, TAG_WORKSPACE); 99 writeNodes(serializer, mNodes); 100 serializer.endTag(null, TAG_WORKSPACE); 101 serializer.endDocument(); 102 serializer.flush(); 103 } 104 writeNodes(XmlSerializer serializer, ArrayList<Pair<String, HashMap<String, Object>>> nodes)105 private static void writeNodes(XmlSerializer serializer, 106 ArrayList<Pair<String, HashMap<String, Object>>> nodes) throws IOException { 107 for (Pair<String, HashMap<String, Object>> node : nodes) { 108 ArrayList<Pair<String, HashMap<String, Object>>> children = null; 109 110 serializer.startTag(null, node.first); 111 for (Map.Entry<String, Object> attr : node.second.entrySet()) { 112 if (ATTR_CHILDREN.equals(attr.getKey())) { 113 children = (ArrayList<Pair<String, HashMap<String, Object>>>) attr.getValue(); 114 } else { 115 serializer.attribute(null, attr.getKey(), (String) attr.getValue()); 116 } 117 } 118 119 if (children != null) { 120 writeNodes(serializer, children); 121 } 122 serializer.endTag(null, node.first); 123 } 124 } 125 126 public class Location { 127 128 final HashMap<String, Object> items = new HashMap<>(); 129 putApp(String packageName, String className)130 public LauncherLayoutBuilder putApp(String packageName, String className) { 131 items.put(ATTR_PACKAGE_NAME, packageName); 132 items.put(ATTR_CLASS_NAME, TextUtils.isEmpty(className) ? packageName : className); 133 mNodes.add(Pair.create(TAG_AUTO_INSTALL, items)); 134 return LauncherLayoutBuilder.this; 135 } 136 putWidget(String packageName, String className, int spanX, int spanY)137 public LauncherLayoutBuilder putWidget(String packageName, String className, 138 int spanX, int spanY) { 139 items.put(ATTR_PACKAGE_NAME, packageName); 140 items.put(ATTR_CLASS_NAME, className); 141 items.put(ATTR_SPAN_X, Integer.toString(spanX)); 142 items.put(ATTR_SPAN_Y, Integer.toString(spanY)); 143 mNodes.add(Pair.create(TAG_APPWIDGET, items)); 144 return LauncherLayoutBuilder.this; 145 } 146 putFolder(int titleResId)147 public FolderBuilder putFolder(int titleResId) { 148 FolderBuilder folderBuilder = new FolderBuilder(); 149 items.put(ATTR_TITLE, Integer.toString(titleResId)); 150 items.put(ATTR_CHILDREN, folderBuilder.mChildren); 151 mNodes.add(Pair.create(TAG_FOLDER, items)); 152 return folderBuilder; 153 } 154 } 155 156 public class FolderBuilder { 157 158 final ArrayList<Pair<String, HashMap<String, Object>>> mChildren = new ArrayList<>(); 159 addApp(String packageName, String className)160 public FolderBuilder addApp(String packageName, String className) { 161 HashMap<String, Object> items = new HashMap<>(); 162 items.put(ATTR_PACKAGE_NAME, packageName); 163 items.put(ATTR_CLASS_NAME, TextUtils.isEmpty(className) ? packageName : className); 164 mChildren.add(Pair.create(TAG_AUTO_INSTALL, items)); 165 return this; 166 } 167 build()168 public LauncherLayoutBuilder build() { 169 return LauncherLayoutBuilder.this; 170 } 171 } 172 } 173