📄 pl_codegen.py
字号:
'use Wx 0.15 qw[:allclasses];\nuse strict;\n' ] if not config.preferences.write_timestamp: header_lines[0] = '# generated by wxGlade %s%s\n' % \ (common.version, common.generated_from()) multiple_files = multi_files if not multiple_files: global output_file, output_file_name if not _overwrite and os.path.isfile(out_path): # the file exists, we must keep all the lines not inside a wxGlade # block. NOTE: this may cause troubles if out_path is not a valid # perl file, so be careful! previous_source = SourceFileContent(out_path) else: # if the file doesn't exist, create it and write the ``intro'' previous_source = None output_file = cStringIO.StringIO() output_file_name = out_path output_file.write('#!/usr/bin/perl -w -- \n') for line in header_lines: output_file.write(line) output_file.write('#<%swxGlade extra_modules>\n' % nonce) output_file.write('\n') else: previous_source = None global out_dir if not os.path.isdir(out_path): raise XmlParsingError("'path' must be a directory when generating"\ " multiple output files") out_dir = out_pathdef finalize(): """\ Writer ``finalization'' function: flushes buffers, closes open files, ... """ if previous_source is not None: # insert all the new custom classes inside the old file tag = '#<%swxGlade insert new_classes>' % nonce if previous_source.new_classes: code = "".join(previous_source.new_classes) else: code = "" previous_source.content = previous_source.content.replace(tag, code) tag = '#<%swxGlade extra_modules>\n' % nonce code = "".join(_current_extra_modules.keys()) previous_source.content = previous_source.content.replace(tag, code) # now remove all the remaining <123415wxGlade ...> tags from the # source: this may happen if we're not generating multiple files, # and one of the container class names is changed import re tags = re.findall('(#<%swxGlade replace ([a-zA-Z_]\w*) +\w+>)' % nonce, previous_source.content) for tag in tags: indent = previous_source.spaces.get(tag[1], '\t') comment = '%s# content of this block not found: ' \ 'did you rename this class?\n' % indent previous_source.content = previous_source.content.replace(tag[0], comment) tags = re.findall('#<%swxGlade event_handlers \w+>' % nonce, previous_source.content) for tag in tags: previous_source.content = previous_source.content.replace(tag, "") # write the new file contents to disk common.save_file(previous_source.name, previous_source.content, 'codegen') elif not multiple_files: global output_file em = "".join(_current_extra_modules.keys()) content = output_file.getvalue().replace( '#<%swxGlade extra_modules>\n' % nonce, em) output_file.close() try: common.save_file(output_file_name, content, 'codegen') # make the file executable if _app_added: os.chmod(output_file_name, 0755) except IOError, e: raise XmlParsingError(str(e)) except OSError: pass # this isn't necessary a bad error del output_filedef test_attribute(obj): """\ Returns True if 'obj' should be added as an attribute of its parent's class, False if it should be created as a local variable of __do_layout. To do so, tests for the presence of the special property 'attribute' """ try: return int(obj.properties['attribute']) except (KeyError, ValueError): return True # this is the defaultdef add_object(top_obj, sub_obj): """\ adds the code to build 'sub_obj' to the class body of 'top_obj'. """ try: klass = classes[top_obj.klass] except KeyError: klass = classes[top_obj.klass] = ClassLines() try: builder = obj_builders[sub_obj.base] except KeyError: # no code generator found: write a comment about it klass.init.extend(['\n', '# code for %s (type %s) not generated: ' 'no suitable writer found' % (sub_obj.name, sub_obj.klass),'\n']) else: try: init, props, layout = builder.get_code(sub_obj) except: print sub_obj raise # this shouldn't happen if sub_obj.in_windows: # the object is a wxWindow instance # --- patch 2002-08-26 ------------------------------------------ if sub_obj.is_container and not sub_obj.is_toplevel: init.reverse() klass.parents_init.extend(init) else: klass.init.extend(init) # --------------------------------------------------------------- mycn = getattr(builder, 'cn', cn) if hasattr(builder, 'get_events'): evts = builder.get_events(sub_obj) for id, event, handler in evts: klass.event_handlers.append((id, event, handler)) elif 'events' in sub_obj.properties: id_name, id = generate_code_id(sub_obj) #if id == '-1': id = 'self.%s.GetId()' % sub_obj.name if id == '-1': id = '#$self->%s' % sub_obj.name for event, handler in sub_obj.properties['events'].iteritems(): klass.event_handlers.append((id, event, handler)) else: # the object is a sizer if sub_obj.base == 'wxStaticBoxSizer': klass.parents_init.insert(1, init.pop(0)) # ${staticboxsizername}_staticbox klass.sizers_init.extend(init) klass.props.extend(props) klass.layout.extend(layout) if multiple_files and \ (sub_obj.is_toplevel and sub_obj.base != sub_obj.klass): key = 'use %s;\n' % sub_obj.klass klass.dependencies[key] = 1## for dep in _widget_extra_modules.get(sub_obj.base, []): for dep in getattr(obj_builders.get(sub_obj.base), 'import_modules', []): klass.dependencies[dep] = 1def add_sizeritem(toplevel, sizer, obj, option, flag, border): """\ writes the code to add the object 'obj' to the sizer 'sizer' in the 'toplevel' object. """ # an ugly hack to allow the addition of spacers: if obj_name can be parsed # as a couple of integers, it is the size of the spacer to add obj_name = obj.name try: w, h = [ int(s) for s in obj_name.split(',') ] except ValueError: if obj.in_windows: # attribute is a special property, which tells us if the object # is a local variable or an attribute of its paren if test_attribute(obj): obj_name = '$self->{%s}' % obj_name if obj.base == 'wxNotebook' and for_version < (2, 6): # deprecated since wxWidgets 2.5.3 obj_name = 'Wx::NotebookSizer->new(%s)' % obj_name elif obj_name[0:1] != '$': obj_name = '$self->{%s}' % obj_name try: klass = classes[toplevel.klass] except KeyError: klass = classes[toplevel.klass] = ClassLines() buffer = '$self->{%s}->Add(%s, %s, %s, %s);\n' % \ (sizer.name, obj_name, option, flag, border) klass.layout.append(buffer)new_defaults = { '$parent' : '\t$parent = undef unless defined $parent;\n' , '$id' : '\t$id = -1 unless defined $id;\n' , '$title' : '\t$title = "" unless defined $title;\n' , '$pos' : '\t$pos = wxDefaultPosition unless defined $pos;\n' , '$size' : '\t$size = wxDefaultSize unless defined $size;\n' , '$name' : '\t$name = "" unless defined $name;\n\n',# '$style' is a special case}def add_class(code_obj): """\ Generates the code for a custom class. """ global _current_extra_modules if not multiple_files: # in this case, previous_source is the SourceFileContent instance # that keeps info about the single file to generate prev_src = previous_source else: # let's see if the file to generate exists, and in this case # create a SourceFileContent instance filename = os.path.join(out_dir, code_obj.klass + '.pm') # MODULE!! if not os.path.exists(filename): prev_src = None else: prev_src = SourceFileContent(filename) _current_extra_modules = {} if classes.has_key(code_obj.klass) and classes[code_obj.klass].done: return # the code has already been generated try: builder = obj_builders[code_obj.base] except KeyError: print code_obj raise # this is an error, let the exception be raised if prev_src is not None and prev_src.classes.has_key(code_obj.klass): is_new = False else: # this class wasn't in the previous version of the source (if any) is_new = True mods = getattr(builder, 'extra_modules', []) if mods: for m in mods: _current_extra_modules[m] = 1 buffer = [] write = buffer.append if not classes.has_key(code_obj.klass): # if the class body was empty, create an empty ClassLines classes[code_obj.klass] = ClassLines() new_signature = getattr(builder, 'new_signature', [] ) if _use_gettext and not is_new: classes[code_obj.klass].dependencies[ "use Wx::Locale gettext => '_T';\n"]=1 if is_new: write('package %s;\n\n' % code_obj.klass ) write('use Wx qw[:everything];\nuse base qw(%s);\nuse strict;\n\n' % code_obj.base.replace('wx','Wx::',1) ) if _use_gettext: if multiple_files: classes[code_obj.klass].dependencies[ "use Wx::Locale gettext => '_T';\n"]=1 else: write("use Wx::Locale gettext => '_T';\n") if multiple_files: # write the module dependecies for this class (package) write('# begin wxGlade: ::dependencies\n') for module in classes[code_obj.klass].dependencies: write(module) write('# end wxGlade\n') write('\n') write('sub new {\n') write("\tmy( $self, %s ) = @_;\n" % ", ".join( new_signature ) ) if new_signature: for k in new_signature : if new_defaults.has_key(k) : write( new_defaults[k] ) else: new_signature = [ '@_[1 .. $#_]' ] # shift(@_)->SUPER::new(@_); print code_obj.klass + " did not declare new_defaults " # constructor (new) begin tag write('# begin wxGlade: %s::new\n\n' % code_obj.klass) prop = code_obj.properties style = prop.get("style", None) if style: write('\t$style = %s \n\t\tunless defined $style;\n\n' % style) # constructor (new) write('\t$self = $self->SUPER::new( %s );\n' % ", ".join( new_signature )) init_lines = classes[code_obj.klass].init parents_init = classes[code_obj.klass].parents_init parents_init.reverse() for l in parents_init: write('\t' +l) for l in init_lines: write('\t' +l) # now check if there are extra lines to add to the init method if hasattr(builder, 'get_init_code'): for l in builder.get_init_code(code_obj): write('\t' + l) write('\n\t$self->__set_properties();\n') write('\t$self->__do_layout();\n\n') event_handlers = classes[code_obj.klass].event_handlers if hasattr(builder, 'get_events'): for id, event, handler in builder.get_events(code_obj): event_handlers.append((id, event, handler)) for win_id, event, handler in event_handlers: if win_id.startswith('#'): win_id = '$self->{' + win_id[8:] + '}->GetId' write('\tWx::Event::%s($self, %s, \\&%s);\n' % \ (event, win_id, handler)) if event_handlers: write('\n') write('# end wxGlade\n') if is_new: write('\treturn $self;\n\n') write('}\n\n') if prev_src is not None and not is_new: # replace the lines inside the ::new wxGlade block with the new ones tag = '#<%swxGlade replace %s %s>' % (nonce, code_obj.klass, 'new') if prev_src.content.find(tag) < 0: # no __init__ tag found, issue a warning and do nothing print >> sys.stderr, "WARNING: wxGlade ::new block not found," \ " constructor code NOT generated" else: prev_src.content = prev_src.content.replace(tag, "".join(buffer)) buffer = [] write = buffer.append # __set_properties obj_p = getattr(builder, 'get_properties_code', generate_common_properties)(code_obj) obj_p.extend(classes[code_obj.klass].props) write_body = len(obj_p) if is_new: write('\nsub __set_properties {\n\tmy $self = shift;\n\n') write('# begin wxGlade: %s::__set_properties\n\n' % code_obj.klass)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -