OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/python2.4 |
| 2 # Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. |
| 5 |
| 6 '''The 'grit resize' tool. |
| 7 ''' |
| 8 |
| 9 import getopt |
| 10 import os |
| 11 import types |
| 12 |
| 13 from grit.tool import interface |
| 14 from grit.tool import build |
| 15 from grit import grd_reader |
| 16 from grit import pseudo |
| 17 from grit import util |
| 18 |
| 19 from grit.node import include |
| 20 from grit.node import structure |
| 21 from grit.node import message |
| 22 |
| 23 from grit.format import rc_header |
| 24 |
| 25 |
| 26 # Template for the .vcproj file, with a couple of [[REPLACEABLE]] parts. |
| 27 PROJECT_TEMPLATE = '''\ |
| 28 <?xml version="1.0" encoding="Windows-1252"?> |
| 29 <VisualStudioProject |
| 30 ProjectType="Visual C++" |
| 31 Version="7.10" |
| 32 Name="[[DIALOG_NAME]]" |
| 33 ProjectGUID="[[PROJECT_GUID]]" |
| 34 Keyword="Win32Proj"> |
| 35 <Platforms> |
| 36 <Platform |
| 37 Name="Win32"/> |
| 38 </Platforms> |
| 39 <Configurations> |
| 40 <Configuration |
| 41 Name="Debug|Win32" |
| 42 OutputDirectory="Debug" |
| 43 IntermediateDirectory="Debug" |
| 44 ConfigurationType="1" |
| 45 CharacterSet="2"> |
| 46 </Configuration> |
| 47 </Configurations> |
| 48 <References> |
| 49 </References> |
| 50 <Files> |
| 51 <Filter |
| 52 Name="Resource Files" |
| 53 Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;
jpe;resx" |
| 54 UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
"> |
| 55 <File |
| 56 RelativePath=".\[[DIALOG_NAME]].rc"> |
| 57 </File> |
| 58 </Filter> |
| 59 </Files> |
| 60 <Globals> |
| 61 </Globals> |
| 62 </VisualStudioProject>''' |
| 63 |
| 64 |
| 65 # Template for the .rc file with a couple of [[REPLACEABLE]] parts. |
| 66 # TODO(joi) Improve this (and the resource.h template) to allow saving and then |
| 67 # reopening of the RC file in Visual Studio. Currently you can only open it |
| 68 # once and change it, then after you close it you won't be able to reopen it. |
| 69 RC_TEMPLATE = '''\ |
| 70 // Copyright (c) Google Inc. 2005 |
| 71 // All rights reserved. |
| 72 // This file is automatically generated by GRIT and intended for editing |
| 73 // the layout of the dialogs contained in it. Do not edit anything but the |
| 74 // dialogs. Any changes made to translateable portions of the dialogs will |
| 75 // be ignored by GRIT. |
| 76 |
| 77 #include "resource.h" |
| 78 #include <winresrc.h> |
| 79 #ifdef IDC_STATIC |
| 80 #undef IDC_STATIC |
| 81 #endif |
| 82 #define IDC_STATIC (-1) |
| 83 |
| 84 LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL |
| 85 |
| 86 #pragma code_page([[CODEPAGE_NUM]]) |
| 87 |
| 88 [[INCLUDES]] |
| 89 |
| 90 [[DIALOGS]] |
| 91 ''' |
| 92 |
| 93 |
| 94 # Template for the resource.h file with a couple of [[REPLACEABLE]] parts. |
| 95 HEADER_TEMPLATE = '''\ |
| 96 // Copyright (c) Google Inc. 2005 |
| 97 // All rights reserved. |
| 98 // This file is automatically generated by GRIT. Do not edit. |
| 99 |
| 100 #pragma once |
| 101 |
| 102 // Edit commands |
| 103 #define ID_EDIT_CLEAR 0xE120 |
| 104 #define ID_EDIT_CLEAR_ALL 0xE121 |
| 105 #define ID_EDIT_COPY 0xE122 |
| 106 #define ID_EDIT_CUT 0xE123 |
| 107 #define ID_EDIT_FIND 0xE124 |
| 108 #define ID_EDIT_PASTE 0xE125 |
| 109 #define ID_EDIT_PASTE_LINK 0xE126 |
| 110 #define ID_EDIT_PASTE_SPECIAL 0xE127 |
| 111 #define ID_EDIT_REPEAT 0xE128 |
| 112 #define ID_EDIT_REPLACE 0xE129 |
| 113 #define ID_EDIT_SELECT_ALL 0xE12A |
| 114 #define ID_EDIT_UNDO 0xE12B |
| 115 #define ID_EDIT_REDO 0xE12C |
| 116 |
| 117 |
| 118 [[DEFINES]] |
| 119 ''' |
| 120 |
| 121 |
| 122 class ResizeDialog(interface.Tool): |
| 123 '''Generates an RC file, header and Visual Studio project that you can use |
| 124 with Visual Studio's GUI resource editor to modify the layout of dialogs for |
| 125 the language of your choice. You then use the RC file, after you resize the |
| 126 dialog, for the language or languages of your choice, using the <skeleton> child |
| 127 of the <structure> node for the dialog. The translateable bits of the dialog |
| 128 will be ignored when you use the <skeleton> node (GRIT will instead use the |
| 129 translateable bits from the original dialog) but the layout changes you make |
| 130 will be used. Note that your layout changes must preserve the order of the |
| 131 translateable elements in the RC file. |
| 132 |
| 133 Usage: grit resize [-f BASEFOLDER] [-l LANG] [-e RCENCODING] DIALOGID* |
| 134 |
| 135 Arguments: |
| 136 DIALOGID The 'name' attribute of a dialog to output for resizing. Zero |
| 137 or more of these parameters can be used. If none are |
| 138 specified, all dialogs from the input .grd file are output. |
| 139 |
| 140 Options: |
| 141 |
| 142 -f BASEFOLDER The project will be created in a subfolder of BASEFOLDER. |
| 143 The name of the subfolder will be the first DIALOGID you |
| 144 specify. Defaults to '.' |
| 145 |
| 146 -l LANG Specifies that the RC file should contain a dialog translated |
| 147 into the language LANG. The default is a cp1252-representable |
| 148 pseudotranslation, because Visual Studio's GUI RC editor only |
| 149 supports single-byte encodings. |
| 150 |
| 151 -c CODEPAGE Code page number to indicate to the RC compiler the encoding |
| 152 of the RC file, default is something reasonable for the |
| 153 language you selected (but this does not work for every single |
| 154 language). See details on codepages below. NOTE that you do |
| 155 not need to specify the codepage unless the tool complains |
| 156 that it's not sure which codepage to use. See the following |
| 157 page for codepage numbers supported by Windows: |
| 158 http://www.microsoft.com/globaldev/reference/wincp.mspx |
| 159 |
| 160 -D NAME[=VAL] Specify a C-preprocessor-like define NAME with optional |
| 161 value VAL (defaults to 1) which will be used to control |
| 162 conditional inclusion of resources. |
| 163 |
| 164 |
| 165 IMPORTANT NOTE: For now, the tool outputs a UTF-8 encoded file for any language |
| 166 that can not be represented in cp1252 (i.e. anything other than Western |
| 167 European languages). You will need to open this file in a text editor and |
| 168 save it using the codepage indicated in the #pragma code_page(XXXX) command |
| 169 near the top of the file, before you open it in Visual Studio. |
| 170 |
| 171 ''' |
| 172 |
| 173 # TODO(joi) It would be cool to have this tool note the Perforce revision |
| 174 # of the original RC file somewhere, such that the <skeleton> node could warn |
| 175 # if the original RC file gets updated without the skeleton file being updated
. |
| 176 |
| 177 # TODO(joi) Would be cool to have option to add the files to Perforce |
| 178 |
| 179 def __init__(self): |
| 180 self.lang = pseudo.PSEUDO_LANG |
| 181 self.defines = {} |
| 182 self.base_folder = '.' |
| 183 self.codepage_number = 1252 |
| 184 self.codepage_number_specified_explicitly = False |
| 185 |
| 186 def SetLanguage(self, lang): |
| 187 '''Sets the language code to output things in. |
| 188 ''' |
| 189 self.lang = lang |
| 190 if not self.codepage_number_specified_explicitly: |
| 191 self.codepage_number = util.LanguageToCodepage(lang) |
| 192 |
| 193 def GetEncoding(self): |
| 194 if self.codepage_number == 1200: |
| 195 return 'utf_16' |
| 196 if self.codepage_number == 65001: |
| 197 return 'utf_8' |
| 198 return 'cp%d' % self.codepage_number |
| 199 |
| 200 def ShortDescription(self): |
| 201 return 'Generate a file where you can resize a given dialog.' |
| 202 |
| 203 def Run(self, opts, args): |
| 204 self.SetOptions(opts) |
| 205 |
| 206 own_opts, args = getopt.getopt(args, 'l:f:c:D:') |
| 207 for key, val in own_opts: |
| 208 if key == '-l': |
| 209 self.SetLanguage(val) |
| 210 if key == '-f': |
| 211 self.base_folder = val |
| 212 if key == '-c': |
| 213 self.codepage_number = int(val) |
| 214 self.codepage_number_specified_explicitly = True |
| 215 if key == '-D': |
| 216 name, val = build.ParseDefine(val) |
| 217 self.defines[name] = val |
| 218 |
| 219 res_tree = grd_reader.Parse(opts.input, debug=opts.extra_verbose) |
| 220 res_tree.OnlyTheseTranslations([self.lang]) |
| 221 res_tree.RunGatherers(True) |
| 222 |
| 223 # Dialog IDs are either explicitly listed, or we output all dialogs from the |
| 224 # .grd file |
| 225 dialog_ids = args |
| 226 if not len(dialog_ids): |
| 227 for node in res_tree: |
| 228 if node.name == 'structure' and node.attrs['type'] == 'dialog': |
| 229 dialog_ids.append(node.attrs['name']) |
| 230 |
| 231 self.Process(res_tree, dialog_ids) |
| 232 |
| 233 def Process(self, grd, dialog_ids): |
| 234 '''Outputs an RC file and header file for the dialog 'dialog_id' stored in |
| 235 resource tree 'grd', to self.base_folder, as discussed in this class's |
| 236 documentation. |
| 237 |
| 238 Arguments: |
| 239 grd: grd = grd_reader.Parse(...); grd.RunGatherers() |
| 240 dialog_ids: ['IDD_MYDIALOG', 'IDD_OTHERDIALOG'] |
| 241 ''' |
| 242 grd.SetOutputContext(self.lang, self.defines) |
| 243 |
| 244 project_name = dialog_ids[0] |
| 245 |
| 246 dir_path = os.path.join(self.base_folder, project_name) |
| 247 if not os.path.isdir(dir_path): |
| 248 os.mkdir(dir_path) |
| 249 |
| 250 # If this fails then we're not on Windows (or you don't have the required |
| 251 # win32all Python libraries installed), so what are you doing mucking |
| 252 # about with RC files anyway? :) |
| 253 import pythoncom |
| 254 |
| 255 # Create the .vcproj file |
| 256 project_text = PROJECT_TEMPLATE.replace( |
| 257 '[[PROJECT_GUID]]', str(pythoncom.CreateGuid()) |
| 258 ).replace('[[DIALOG_NAME]]', project_name) |
| 259 fname = os.path.join(dir_path, '%s.vcproj' % project_name) |
| 260 self.WriteFile(fname, project_text) |
| 261 print "Wrote %s" % fname |
| 262 |
| 263 # Create the .rc file |
| 264 # Output all <include> nodes since the dialogs might depend on them (e.g. |
| 265 # for icons and bitmaps). |
| 266 include_items = [] |
| 267 for node in grd: |
| 268 if isinstance(node, include.IncludeNode): |
| 269 formatter = node.ItemFormatter('rc_all') |
| 270 if formatter: |
| 271 include_items.append(formatter.Format(node, self.lang)) |
| 272 rc_text = RC_TEMPLATE.replace('[[CODEPAGE_NUM]]', |
| 273 str(self.codepage_number)) |
| 274 rc_text = rc_text.replace('[[INCLUDES]]', ''.join(include_items)) |
| 275 |
| 276 # Then output the dialogs we have been asked to output. |
| 277 dialogs = [] |
| 278 for dialog_id in dialog_ids: |
| 279 node = grd.GetNodeById(dialog_id) |
| 280 # TODO(joi) Add exception handling for better error reporting |
| 281 formatter = node.ItemFormatter('rc_all') |
| 282 dialogs.append(formatter.Format(node, self.lang)) |
| 283 rc_text = rc_text.replace('[[DIALOGS]]', ''.join(dialogs)) |
| 284 |
| 285 fname = os.path.join(dir_path, '%s.rc' % project_name) |
| 286 self.WriteFile(fname, rc_text, self.GetEncoding()) |
| 287 print "Wrote %s" % fname |
| 288 |
| 289 # Create the resource.h file |
| 290 header_defines = [] |
| 291 for node in grd: |
| 292 formatter = node.ItemFormatter('rc_header') |
| 293 if formatter and not isinstance(formatter, rc_header.TopLevel): |
| 294 header_defines.append(formatter.Format(node, self.lang)) |
| 295 header_text = HEADER_TEMPLATE.replace('[[DEFINES]]', ''.join(header_defines)
) |
| 296 fname = os.path.join(dir_path, 'resource.h') |
| 297 self.WriteFile(fname, header_text) |
| 298 print "Wrote %s" % fname |
| 299 |
| 300 def WriteFile(self, filename, contents, encoding='cp1252'): |
| 301 f = util.WrapOutputStream(file(filename, 'wb'), encoding) |
| 302 f.write(contents) |
| 303 f.close() |
OLD | NEW |