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_TITLE_TEXT = "titleText"; 51 private static final String ATTR_SCREEN = "screen"; 52 53 // x and y can be specified as negative integers, in which case -1 represents the 54 // last row / column, -2 represents the second last, and so on. 55 private static final String ATTR_X = "x"; 56 private static final String ATTR_Y = "y"; 57 private static final String ATTR_SPAN_X = "spanX"; 58 private static final String ATTR_SPAN_Y = "spanY"; 59 60 private static final String ATTR_CHILDREN = "children"; 61 62 63 // Style attrs -- "Extra" 64 private static final String ATTR_KEY = "key"; 65 private static final String ATTR_VALUE = "value"; 66 67 private static final String CONTAINER_DESKTOP = "desktop"; 68 private static final String CONTAINER_HOTSEAT = "hotseat"; 69 70 private final ArrayList<Pair<String, HashMap<String, Object>>> mNodes = new ArrayList<>(); 71 atHotseat(int rank)72 public Location atHotseat(int rank) { 73 Location l = new Location(); 74 l.items.put(ATTR_CONTAINER, CONTAINER_HOTSEAT); 75 l.items.put(ATTR_RANK, Integer.toString(rank)); 76 return l; 77 } 78 atWorkspace(int x, int y, int screen)79 public Location atWorkspace(int x, int y, int screen) { 80 Location l = new Location(); 81 l.items.put(ATTR_CONTAINER, CONTAINER_DESKTOP); 82 l.items.put(ATTR_X, Integer.toString(x)); 83 l.items.put(ATTR_Y, Integer.toString(y)); 84 l.items.put(ATTR_SCREEN, Integer.toString(screen)); 85 return l; 86 } 87 build()88 public String build() throws IOException { 89 StringWriter writer = new StringWriter(); 90 build(writer); 91 return writer.toString(); 92 } 93 build(Writer writer)94 public void build(Writer writer) throws IOException { 95 XmlSerializer serializer = Xml.newSerializer(); 96 serializer.setOutput(writer); 97 98 serializer.startDocument("UTF-8", true); 99 serializer.startTag(null, TAG_WORKSPACE); 100 writeNodes(serializer, mNodes); 101 serializer.endTag(null, TAG_WORKSPACE); 102 serializer.endDocument(); 103 serializer.flush(); 104 } 105 writeNodes(XmlSerializer serializer, ArrayList<Pair<String, HashMap<String, Object>>> nodes)106 private static void writeNodes(XmlSerializer serializer, 107 ArrayList<Pair<String, HashMap<String, Object>>> nodes) throws IOException { 108 for (Pair<String, HashMap<String, Object>> node : nodes) { 109 ArrayList<Pair<String, HashMap<String, Object>>> children = null; 110 111 serializer.startTag(null, node.first); 112 for (Map.Entry<String, Object> attr : node.second.entrySet()) { 113 if (ATTR_CHILDREN.equals(attr.getKey())) { 114 children = (ArrayList<Pair<String, HashMap<String, Object>>>) attr.getValue(); 115 } else { 116 serializer.attribute(null, attr.getKey(), (String) attr.getValue()); 117 } 118 } 119 120 if (children != null) { 121 writeNodes(serializer, children); 122 } 123 serializer.endTag(null, node.first); 124 } 125 } 126 127 public class Location { 128 129 final HashMap<String, Object> items = new HashMap<>(); 130 putApp(String packageName, String className)131 public LauncherLayoutBuilder putApp(String packageName, String className) { 132 items.put(ATTR_PACKAGE_NAME, packageName); 133 items.put(ATTR_CLASS_NAME, TextUtils.isEmpty(className) ? packageName : className); 134 mNodes.add(Pair.create(TAG_AUTO_INSTALL, items)); 135 return LauncherLayoutBuilder.this; 136 } 137 putWidget(String packageName, String className, int spanX, int spanY)138 public LauncherLayoutBuilder putWidget(String packageName, String className, 139 int spanX, int spanY) { 140 items.put(ATTR_PACKAGE_NAME, packageName); 141 items.put(ATTR_CLASS_NAME, className); 142 items.put(ATTR_SPAN_X, Integer.toString(spanX)); 143 items.put(ATTR_SPAN_Y, Integer.toString(spanY)); 144 mNodes.add(Pair.create(TAG_APPWIDGET, items)); 145 return LauncherLayoutBuilder.this; 146 } 147 putFolder(int titleResId)148 public FolderBuilder putFolder(int titleResId) { 149 items.put(ATTR_TITLE, Integer.toString(titleResId)); 150 return putFolder(); 151 } 152 putFolder(String title)153 public FolderBuilder putFolder(String title) { 154 items.put(ATTR_TITLE_TEXT, title); 155 return putFolder(); 156 } 157 putFolder()158 private FolderBuilder putFolder() { 159 FolderBuilder folderBuilder = new FolderBuilder(); 160 items.put(ATTR_CHILDREN, folderBuilder.mChildren); 161 mNodes.add(Pair.create(TAG_FOLDER, items)); 162 return folderBuilder; 163 } 164 } 165 166 public class FolderBuilder { 167 168 final ArrayList<Pair<String, HashMap<String, Object>>> mChildren = new ArrayList<>(); 169 addApp(String packageName, String className)170 public FolderBuilder addApp(String packageName, String className) { 171 HashMap<String, Object> items = new HashMap<>(); 172 items.put(ATTR_PACKAGE_NAME, packageName); 173 items.put(ATTR_CLASS_NAME, TextUtils.isEmpty(className) ? packageName : className); 174 mChildren.add(Pair.create(TAG_AUTO_INSTALL, items)); 175 return this; 176 } 177 build()178 public LauncherLayoutBuilder build() { 179 return LauncherLayoutBuilder.this; 180 } 181 } 182 } 183