From 895139e14e002ce0cbce19df73b420effe2378d4 Mon Sep 17 00:00:00 2001 From: pszsh Date: Sat, 7 Feb 2026 22:29:14 -0800 Subject: [PATCH] init --- .gitignore | 1 + __init__.py | 24 ++ backend/__init__.py | 2 + backend/layer.py | 264 ++++++++++++++++++++ backend/manager.py | 181 ++++++++++++++ backend/ref.py | 543 ++++++++++++++++++++++++++++++++++++++++ backend/resolvers.py | 112 +++++++++ backend/serializer.py | 80 ++++++ backend/storage.py | 134 ++++++++++ backend/thumbnails.py | 89 +++++++ debug.py | 87 +++++++ debug2.py | 236 ++++++++++++++++++ interface.py | 561 ++++++++++++++++++++++++++++++++++++++++++ metadata.json | 11 + pcbnew.py.md | 352 ++++++++++++++++++++++++++ 15 files changed, 2677 insertions(+) create mode 100644 .gitignore create mode 100644 __init__.py create mode 100644 backend/__init__.py create mode 100644 backend/layer.py create mode 100644 backend/manager.py create mode 100644 backend/ref.py create mode 100644 backend/resolvers.py create mode 100644 backend/serializer.py create mode 100644 backend/storage.py create mode 100644 backend/thumbnails.py create mode 100644 debug.py create mode 100644 debug2.py create mode 100644 interface.py create mode 100644 metadata.json create mode 100644 pcbnew.py.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f5e96db --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +venv \ No newline at end of file diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..6c256db --- /dev/null +++ b/__init__.py @@ -0,0 +1,24 @@ +# __init__.py +import pcbnew +import os + +try: + from .interface import ShowWindow + + class LogicalLayersPlugin(pcbnew.ActionPlugin): + def defaults(self): + self.name = "Logical Layers" + self.category = "Layout" + self.description = "Manage logical layers" + self.show_toolbar_button = True + self.icon_file_name = os.path.join(os.path.dirname(__file__), "icon.png") + + def Run(self): + ShowWindow() + + LogicalLayersPlugin().register() + +except Exception as e: + import sys + + print(f"LogicalLayers Init Error: {e}", file=sys.stderr) diff --git a/backend/__init__.py b/backend/__init__.py new file mode 100644 index 0000000..43af50a --- /dev/null +++ b/backend/__init__.py @@ -0,0 +1,2 @@ +# backend/__init__.py +from .manager import manager \ No newline at end of file diff --git a/backend/layer.py b/backend/layer.py new file mode 100644 index 0000000..75b036b --- /dev/null +++ b/backend/layer.py @@ -0,0 +1,264 @@ +# backend/layer.py +import pcbnew +import re +import traceback +from .resolvers import get_item_uuid, resolve_to_trackable_item, find_item_by_uuid +from .serializer import Serializer + +class Layer: + def __init__(self, name, manager): + self.name = name + self.manager = manager + self.visible = True + self.on_board_items = [] # List of {'uuid': str, 'class': str} + self.stored_items = [] # List of filenames (str) pointing to item JSONs + + def add_item(self, item): + if not item: return False + uuid = get_item_uuid(item) + if not uuid: return False + + cls = item.GetClass() + for entry in self.on_board_items: + if entry['uuid'] == uuid: return False + self.on_board_items.append({'uuid': uuid, 'class': cls}) + return True + + def _clear_selection_safe(self): + try: + sel = pcbnew.GetCurrentSelection() + items = [i for i in sel] + for item in items: + if hasattr(item, 'ClearSelected'): item.ClearSelected() + if hasattr(item, 'ClearBrightened'): item.ClearBrightened() + except: pass + + def hide(self): + self.manager.log(f"Layer {self.name}: Hiding...") + try: + board = pcbnew.GetBoard() + self._clear_selection_safe() + pcbnew.Refresh() + + new_stored_items = list(self.stored_items) + items_to_remove = [] + failed_entries = [] + + for entry in self.on_board_items: + try: + uuid = entry['uuid'] + item = find_item_by_uuid(board, uuid) + if not item: + self.manager.log(f"Hide: Item {uuid} not found (skipping)") + continue + + sexpr, err = Serializer.serialize(item) + if not sexpr: + self.manager.log(f"Hide: Serialize failed {uuid}: {err}") + failed_entries.append(entry) + continue + + item_data = {'class': item.GetClass(), 'sexpr': sexpr, 'uuid': uuid} + if hasattr(item, 'GetReference'): item_data['ref'] = item.GetReference() + if hasattr(item, 'GetNetname'): item_data['net'] = item.GetNetname() + + filename = self.manager.storage.save_item(item_data, uuid) + if filename: + new_stored_items.append(filename) + items_to_remove.append(item) + else: + failed_entries.append(entry) + except Exception as e: + self.manager.log(f"Hide: Error entry {entry}: {e}") + failed_entries.append(entry) + + for item in items_to_remove: + try: + if item.IsLocked(): item.SetLocked(False) + board.Remove(item) + except: pass + + self.stored_items = new_stored_items + self.on_board_items = failed_entries + if not self.on_board_items: self.visible = False + self.manager.save() + self.manager.log("Hide: Complete") + except Exception as e: + self.manager.log(f"Hide: Critical Error: {e}") + self.manager.log(traceback.format_exc()) + + def show(self): + try: + self.manager.log(f"Layer {self.name}: Showing (Force Restore)...") + board = pcbnew.GetBoard() + self.manager.is_restoring = True + + new_on_board_items = list(self.on_board_items) + restored_files = [] + + for filename in self.stored_items: + try: + item_data = self.manager.storage.load_item(filename) + if not item_data: continue + uuid = item_data.get('uuid') + + # Force Restore: Remove existing ghost if present + existing = find_item_by_uuid(board, uuid) + if existing: + try: + if existing.IsLocked(): existing.SetLocked(False) + board.Remove(existing) + except: pass + + item, err = Serializer.deserialize(item_data, board) + if item: + try: + board.Add(item) + new_uuid = get_item_uuid(item) + if new_uuid: + found = any(e['uuid'] == new_uuid for e in new_on_board_items) + if not found: + new_on_board_items.append({'uuid': new_uuid, 'class': item.GetClass()}) + restored_files.append(filename) + except Exception as e: + self.manager.log(f"Show: Add failed {uuid}: {e}") + except Exception as e: + self.manager.log(f"Show: Error file {filename}: {e}") + + self.on_board_items = new_on_board_items + for f in restored_files: + if f in self.stored_items: self.stored_items.remove(f) + + self.visible = True + self.manager.is_restoring = False + self.manager.save() + self.manager.log("Show: Complete") + except Exception as e: + self.manager.log(f"Show: Critical Error: {e}") + self.manager.is_restoring = False + + def delete_content(self, delete_items_from_board): + board = pcbnew.GetBoard() + if self.visible: + if delete_items_from_board: + self._clear_selection_safe() + for entry in self.on_board_items: + item = find_item_by_uuid(board, entry['uuid']) + if item: + try: + if item.IsLocked(): item.SetLocked(False) + board.Remove(item) + except: pass + self.on_board_items = [] + else: + if not delete_items_from_board: + self.manager.is_restoring = True + for filename in self.stored_items: + item_data = self.manager.storage.load_item(filename) + if item_data: + item, err = Serializer.deserialize(item_data, board) + if item: board.Add(item) + self.manager.is_restoring = False + self.stored_items = [] + self.manager.save() + + def clear_items(self): + self.delete_content(delete_items_from_board=True) + + def to_dict(self): + return { + "name": self.name, "visible": self.visible, + "on_board_items": self.on_board_items, "stored_items": self.stored_items + } + + @staticmethod + def from_dict(d, manager): + l = Layer(d["name"], manager) + l.visible = d["visible"] + l.on_board_items = d.get("on_board_items", []) + l.stored_items = d.get("stored_items", []) + return l + + def add_from_text(self, text): + uuids = set(re.findall(r'\(uuid\s+"([^"]+)"\)', text)) + if not uuids: return 0, "No UUIDs found." + board = pcbnew.GetBoard() + count = 0 + for uuid in uuids: + try: + item = board.GetItem(pcbnew.KIID(uuid)) + if item: + trackable = resolve_to_trackable_item(item) + if trackable and self.add_item(trackable): count += 1 + except: pass + self.manager.save() + return count, f"Added {count} items." + + def _get_selection_candidates(self, board): + candidates = [] + try: + sel = pcbnew.GetCurrentSelection() + for item in sel: candidates.append(item) + except: pass + + if not candidates: + # Fallback scan + for lst in [board.GetTracks(), board.GetFootprints(), board.GetDrawings(), board.Zones(), board.Groups()]: + try: + for item in lst: + if item.IsSelected(): candidates.append(item) + except: pass + return candidates + + def add_selection(self): + board = pcbnew.GetBoard() + candidates = self._get_selection_candidates(board) + items_to_add = {} + + def process_item(item): + if item.GetClass() == "PCB_GROUP": + try: + group = pcbnew.Cast_to_PCB_GROUP(item) + for sub in group.GetItems(): process_item(sub) + except: pass + else: + trackable = resolve_to_trackable_item(item) + if trackable: + uuid = get_item_uuid(trackable) + if uuid: items_to_add[uuid] = trackable + + for item in candidates: process_item(item) + + count = 0 + for uuid, item in items_to_add.items(): + if self.add_item(item): count += 1 + self.manager.save() + return count, f"Added {count} items." + + def remove_selection(self): + board = pcbnew.GetBoard() + candidates = self._get_selection_candidates(board) + uuids_to_remove = set() + + def collect_uuids(item): + if item.GetClass() == "PCB_GROUP": + try: + group = pcbnew.Cast_to_PCB_GROUP(item) + for sub in group.GetItems(): collect_uuids(sub) + except: pass + else: + trackable = resolve_to_trackable_item(item) + if trackable: + uuid = get_item_uuid(trackable) + if uuid: uuids_to_remove.add(uuid) + + for item in candidates: collect_uuids(item) + + initial_count = len(self.on_board_items) + self.on_board_items = [e for e in self.on_board_items if e['uuid'] not in uuids_to_remove] + removed = initial_count - len(self.on_board_items) + self.manager.save() + return removed, f"Removed {removed} items." + + def inspect(self): + return f"Layer: {self.name}\nVisible: {self.visible}\nOn Board: {len(self.on_board_items)}\nStored: {len(self.stored_items)}" \ No newline at end of file diff --git a/backend/manager.py b/backend/manager.py new file mode 100644 index 0000000..10c5907 --- /dev/null +++ b/backend/manager.py @@ -0,0 +1,181 @@ +# backend/manager.py +import pcbnew +import os +import re +from .storage import StorageManager +from .layer import Layer +from .resolvers import find_item_by_uuid, get_item_uuid, resolve_to_trackable_item +from .serializer import Serializer + +class LayerListener(pcbnew.BOARD_LISTENER): + def __init__(self, mgr): + super().__init__() + self.mgr = mgr + + def OnBoardItemAdded(self, item): + if self.mgr.is_restoring: return + if self.mgr.active_layer_index is not None: + try: + layer = self.mgr.layers[self.mgr.active_layer_index] + if layer.visible: + trackable = resolve_to_trackable_item(item) + if trackable: layer.add_item(trackable) + except: pass + +class LayerManager: + def __init__(self): + self.layers = [] + self.active_layer_index = None + self.listener = None + self.last_save_status = "Init" + self.last_save_path = "Session Dir" + self.last_error = "None" + self.settings = {"delete_mode": "ask"} + self.is_restoring = False + self.debug_log = [] + self.storage = StorageManager() + + def log(self, msg): + self.debug_log.append(str(msg)) + print(f"[LayerManager] {msg}") + + def get_log_text(self): return "\n".join(self.debug_log) + def clear_log(self): self.debug_log = [] + + def activate_listener(self): + if not self.listener: + self.listener = LayerListener(self) + pcbnew.GetBoard().AddListener(self.listener) + + def set_active_layer(self, index): + self.active_layer_index = index + if index is not None: self.activate_listener() + + def get_file_path(self): return self.storage.master_file + + def save(self): + if not self.storage.setup_paths(): + self.last_error = "Failed to setup storage paths" + return + for l in self.layers: self.storage.save_layer(l.name, l.to_dict()) + self.storage.update_master(self.layers) + self.last_save_status = "Saved" + self.last_save_path = self.storage.session_dir + + def load(self): + if not self.storage.setup_paths(): + self.last_save_status = "No Board" + return + master = self.storage.load_master() + if master and "layers" in master: + self.layers = [] + for l_meta in master["layers"]: + l_data = self.storage.load_layer(l_meta["name"]) + if l_data: self.layers.append(Layer.from_dict(l_data, self)) + self.last_save_status = "Loaded" + else: + self.last_save_status = "New Session" + + def create_layer(self, name): + l = Layer(name, self) + self.layers.append(l) + self.save() + return l + + def delete_layer(self, index, delete_items): + if 0 <= index < len(self.layers): + l = self.layers[index] + l.delete_content(True) if delete_items else l.delete_content(False) + self.layers.pop(index) + self.save() + + def move_layer_up(self, index): + if index > 0 and index < len(self.layers): + self.layers[index], self.layers[index-1] = self.layers[index-1], self.layers[index] + if self.active_layer_index == index: self.active_layer_index = index - 1 + elif self.active_layer_index == index - 1: self.active_layer_index = index + self.save() + return True + return False + + def move_layer_down(self, index): + if index < len(self.layers) - 1 and index >= 0: + self.layers[index], self.layers[index+1] = self.layers[index+1], self.layers[index] + if self.active_layer_index == index: self.active_layer_index = index + 1 + elif self.active_layer_index == index + 1: self.active_layer_index = index + self.save() + return True + return False + + def analyze_clipboard_text(self, text): + self.log(f"Analyze: Input text length: {len(text)}") + uuids = set(re.findall(r'\(uuid\s+"([^"]+)"\)', text)) + if not uuids: return self.get_log_text() + board = pcbnew.GetBoard() + matched = 0 + def check(item): + try: + if get_item_uuid(item) in uuids: return 1 + except: pass + return 0 + try: + for lst in [board.GetTracks(), board.GetFootprints(), board.GetDrawings(), board.Zones()]: + for item in lst: matched += check(item) + except: pass + self.log(f"Analyze: Total Matches on Board: {matched}") + return self.get_log_text() + + def recover_orphans(self): + if not self.storage.setup_paths(): return 0, "Storage not ready" + tracked_uuids = set() + stored_files = set() + board = pcbnew.GetBoard() + for l in self.layers: + for f in l.stored_items: stored_files.add(f) + for entry in l.on_board_items: tracked_uuids.add(entry['uuid']) + orphans = [] + try: + for f in os.listdir(self.storage.session_dir): + if f.endswith(".json") and f != "$Master$.json" and f not in stored_files: + data = self.storage.load_item(f) + if not data or 'uuid' not in data: continue + uuid = data['uuid'] + if uuid in tracked_uuids or find_item_by_uuid(board, uuid): continue + orphans.append(f) + except Exception as e: return 0, f"Error scanning dir: {e}" + if not orphans: return 0, "No orphans found" + rec_layer = self.create_layer("Recovered") + rec_layer.stored_items = orphans + rec_layer.visible = False + self.save() + return len(orphans), f"Recovered {len(orphans)} items." + + def hard_refresh(self): + self.log("Hard Refresh: Starting...") + board = pcbnew.GetBoard() + for layer in self.layers: + if layer.visible: + valid_on_board = [] + for entry in layer.on_board_items: + uuid = entry['uuid'] + item = find_item_by_uuid(board, uuid) + if item: + sexpr, err = Serializer.serialize(item) + if sexpr: valid_on_board.append(entry) + else: + self.log(f"Refresh: Item {uuid} missing from visible layer {layer.name}") + layer.on_board_items = valid_on_board + else: + for filename in layer.stored_items: + data = self.storage.load_item(filename) + if data and 'uuid' in data: + uuid = data['uuid'] + item = find_item_by_uuid(board, uuid) + if item: + self.log(f"Refresh: Found ghost {uuid} from hidden layer {layer.name}. Removing.") + try: board.Remove(item) + except: pass + self.save() + self.log("Hard Refresh: Complete") + +manager = LayerManager() \ No newline at end of file diff --git a/backend/ref.py b/backend/ref.py new file mode 100644 index 0000000..01f3403 --- /dev/null +++ b/backend/ref.py @@ -0,0 +1,543 @@ +====================================================================== +// File: layer.py +====================================================================== + +# backend/layer.py +import pcbnew +import re +import traceback +from .resolvers import get_item_uuid, resolve_to_trackable_item, find_item_by_uuid +from .serializer import Serializer + +class Layer: + def __init__(self, name, manager): + self.name = name + self.manager = manager + self.visible = True + self.on_board_items = [] # List of {'uuid': str, 'class': str} + self.stored_items = [] # List of filenames (str) pointing to item JSONs + + def add_item(self, item): + if not item: return False + uuid = get_item_uuid(item) + if not uuid: return False + + cls = item.GetClass() + for entry in self.on_board_items: + if entry['uuid'] == uuid: return False + self.on_board_items.append({'uuid': uuid, 'class': cls}) + return True + + def _clear_selection_safe(self): + try: + sel = pcbnew.GetCurrentSelection() + items = [i for i in sel] + for item in items: + if hasattr(item, 'ClearSelected'): item.ClearSelected() + if hasattr(item, 'ClearBrightened'): item.ClearBrightened() + except: pass + + def hide(self): + self.manager.log(f"Layer {self.name}: Hiding...") + try: + board = pcbnew.GetBoard() + self._clear_selection_safe() + pcbnew.Refresh() + + new_stored_items = list(self.stored_items) + items_to_remove = [] + failed_entries = [] + + for entry in self.on_board_items: + try: + uuid = entry['uuid'] + item = find_item_by_uuid(board, uuid) + if not item: + self.manager.log(f"Hide: Item {uuid} not found (skipping)") + continue + + sexpr, err = Serializer.serialize(item) + if not sexpr: + self.manager.log(f"Hide: Serialize failed {uuid}: {err}") + failed_entries.append(entry) + continue + + item_data = {'class': item.GetClass(), 'sexpr': sexpr, 'uuid': uuid} + if hasattr(item, 'GetReference'): item_data['ref'] = item.GetReference() + if hasattr(item, 'GetNetname'): item_data['net'] = item.GetNetname() + + filename = self.manager.storage.save_item(item_data, uuid) + if filename: + new_stored_items.append(filename) + items_to_remove.append(item) + else: + failed_entries.append(entry) + except Exception as e: + self.manager.log(f"Hide: Error entry {entry}: {e}") + failed_entries.append(entry) + + for item in items_to_remove: + try: + if item.IsLocked(): item.SetLocked(False) + board.Remove(item) + except: pass + + self.stored_items = new_stored_items + self.on_board_items = failed_entries + if not self.on_board_items: self.visible = False + self.manager.save() + self.manager.log("Hide: Complete") + except Exception as e: + self.manager.log(f"Hide: Critical Error: {e}") + self.manager.log(traceback.format_exc()) + + def show(self): + try: + self.manager.log(f"Layer {self.name}: Showing (Force Restore)...") + board = pcbnew.GetBoard() + self.manager.is_restoring = True + + new_on_board_items = list(self.on_board_items) + restored_files = [] + + for filename in self.stored_items: + try: + item_data = self.manager.storage.load_item(filename) + if not item_data: continue + uuid = item_data.get('uuid') + + # Force Restore: Remove existing ghost if present + existing = find_item_by_uuid(board, uuid) + if existing: + try: + if existing.IsLocked(): existing.SetLocked(False) + board.Remove(existing) + except: pass + + item, err = Serializer.deserialize(item_data, board) + if item: + try: + board.Add(item) + new_uuid = get_item_uuid(item) + if new_uuid: + found = any(e['uuid'] == new_uuid for e in new_on_board_items) + if not found: + new_on_board_items.append({'uuid': new_uuid, 'class': item.GetClass()}) + restored_files.append(filename) + except Exception as e: + self.manager.log(f"Show: Add failed {uuid}: {e}") + except Exception as e: + self.manager.log(f"Show: Error file {filename}: {e}") + + self.on_board_items = new_on_board_items + for f in restored_files: + if f in self.stored_items: self.stored_items.remove(f) + + self.visible = True + self.manager.is_restoring = False + self.manager.save() + self.manager.log("Show: Complete") + except Exception as e: + self.manager.log(f"Show: Critical Error: {e}") + self.manager.is_restoring = False + + def delete_content(self, delete_items_from_board): + board = pcbnew.GetBoard() + if self.visible: + if delete_items_from_board: + self._clear_selection_safe() + for entry in self.on_board_items: + item = find_item_by_uuid(board, entry['uuid']) + if item: + try: + if item.IsLocked(): item.SetLocked(False) + board.Remove(item) + except: pass + self.on_board_items = [] + else: + if not delete_items_from_board: + self.manager.is_restoring = True + for filename in self.stored_items: + item_data = self.manager.storage.load_item(filename) + if item_data: + item, err = Serializer.deserialize(item_data, board) + if item: board.Add(item) + self.manager.is_restoring = False + self.stored_items = [] + self.manager.save() + + def clear_items(self): + self.delete_content(delete_items_from_board=True) + + def to_dict(self): + return { + "name": self.name, "visible": self.visible, + "on_board_items": self.on_board_items, "stored_items": self.stored_items + } + + @staticmethod + def from_dict(d, manager): + l = Layer(d["name"], manager) + l.visible = d["visible"] + l.on_board_items = d.get("on_board_items", []) + l.stored_items = d.get("stored_items", []) + return l + + def add_from_text(self, text): + uuids = set(re.findall(r'\(uuid\s+"([^"]+)"\)', text)) + if not uuids: return 0, "No UUIDs found." + board = pcbnew.GetBoard() + count = 0 + for uuid in uuids: + try: + item = board.GetItem(pcbnew.KIID(uuid)) + if item: + trackable = resolve_to_trackable_item(item) + if trackable and self.add_item(trackable): count += 1 + except: pass + self.manager.save() + return count, f"Added {count} items." + + def _get_selection_candidates(self, board): + candidates = [] + try: + sel = pcbnew.GetCurrentSelection() + for item in sel: candidates.append(item) + except: pass + + if not candidates: + # Fallback scan + for lst in [board.GetTracks(), board.GetFootprints(), board.GetDrawings(), board.Zones(), board.Groups()]: + try: + for item in lst: + if item.IsSelected(): candidates.append(item) + except: pass + return candidates + + def add_selection(self): + board = pcbnew.GetBoard() + candidates = self._get_selection_candidates(board) + items_to_add = {} + + def process_item(item): + if item.GetClass() == "PCB_GROUP": + try: + group = pcbnew.Cast_to_PCB_GROUP(item) + for sub in group.GetItems(): process_item(sub) + except: pass + else: + trackable = resolve_to_trackable_item(item) + if trackable: + uuid = get_item_uuid(trackable) + if uuid: items_to_add[uuid] = trackable + + for item in candidates: process_item(item) + + count = 0 + for uuid, item in items_to_add.items(): + if self.add_item(item): count += 1 + self.manager.save() + return count, f"Added {count} items." + + def remove_selection(self): + board = pcbnew.GetBoard() + candidates = self._get_selection_candidates(board) + uuids_to_remove = set() + + def collect_uuids(item): + if item.GetClass() == "PCB_GROUP": + try: + group = pcbnew.Cast_to_PCB_GROUP(item) + for sub in group.GetItems(): collect_uuids(sub) + except: pass + else: + trackable = resolve_to_trackable_item(item) + if trackable: + uuid = get_item_uuid(trackable) + if uuid: uuids_to_remove.add(uuid) + + for item in candidates: collect_uuids(item) + + initial_count = len(self.on_board_items) + self.on_board_items = [e for e in self.on_board_items if e['uuid'] not in uuids_to_remove] + removed = initial_count - len(self.on_board_items) + self.manager.save() + return removed, f"Removed {removed} items." + + def inspect(self): + return f"Layer: {self.name}\nVisible: {self.visible}\nOn Board: {len(self.on_board_items)}\nStored: {len(self.stored_items)}" + + +====================================================================== +// File: manager.py +====================================================================== + +# backend/manager.py +import pcbnew +import os +import re +from .storage import StorageManager +from .layer import Layer +from .resolvers import find_item_by_uuid, get_item_uuid, resolve_to_trackable_item +from .serializer import Serializer + +class LayerListener(pcbnew.BOARD_LISTENER): + def __init__(self, mgr): + super().__init__() + self.mgr = mgr + + def OnBoardItemAdded(self, item): + if self.mgr.is_restoring: return + if self.mgr.active_layer_index is not None: + try: + layer = self.mgr.layers[self.mgr.active_layer_index] + if layer.visible: + trackable = resolve_to_trackable_item(item) + if trackable: layer.add_item(trackable) + except: pass + +class LayerManager: + def __init__(self): + self.layers = [] + self.active_layer_index = None + self.listener = None + self.last_save_status = "Init" + self.last_save_path = "Session Dir" + self.last_error = "None" + self.settings = {"delete_mode": "ask"} + self.is_restoring = False + self.debug_log = [] + self.storage = StorageManager() + + def log(self, msg): + self.debug_log.append(str(msg)) + print(f"[LayerManager] {msg}") + + def get_log_text(self): return "\n".join(self.debug_log) + def clear_log(self): self.debug_log = [] + + def activate_listener(self): + if not self.listener: + self.listener = LayerListener(self) + pcbnew.GetBoard().AddListener(self.listener) + + def set_active_layer(self, index): + self.active_layer_index = index + if index is not None: self.activate_listener() + + def get_file_path(self): return self.storage.master_file + + def save(self): + if not self.storage.setup_paths(): + self.last_error = "Failed to setup storage paths" + return + for l in self.layers: self.storage.save_layer(l.name, l.to_dict()) + self.storage.update_master(self.layers) + self.last_save_status = "Saved" + self.last_save_path = self.storage.session_dir + + def load(self): + if not self.storage.setup_paths(): + self.last_save_status = "No Board" + return + master = self.storage.load_master() + if master and "layers" in master: + self.layers = [] + for l_meta in master["layers"]: + l_data = self.storage.load_layer(l_meta["name"]) + if l_data: self.layers.append(Layer.from_dict(l_data, self)) + self.last_save_status = "Loaded" + else: + self.last_save_status = "New Session" + + def create_layer(self, name): + l = Layer(name, self) + self.layers.append(l) + self.save() + return l + + def delete_layer(self, index, delete_items): + if 0 <= index < len(self.layers): + l = self.layers[index] + l.delete_content(True) if delete_items else l.delete_content(False) + self.layers.pop(index) + self.save() + + def move_layer_up(self, index): + if index > 0 and index < len(self.layers): + self.layers[index], self.layers[index-1] = self.layers[index-1], self.layers[index] + if self.active_layer_index == index: self.active_layer_index = index - 1 + elif self.active_layer_index == index - 1: self.active_layer_index = index + self.save() + return True + return False + + def move_layer_down(self, index): + if index < len(self.layers) - 1 and index >= 0: + self.layers[index], self.layers[index+1] = self.layers[index+1], self.layers[index] + if self.active_layer_index == index: self.active_layer_index = index + 1 + elif self.active_layer_index == index + 1: self.active_layer_index = index + self.save() + return True + return False + + def analyze_clipboard_text(self, text): + self.log(f"Analyze: Input text length: {len(text)}") + uuids = set(re.findall(r'\(uuid\s+"([^"]+)"\)', text)) + if not uuids: return self.get_log_text() + board = pcbnew.GetBoard() + matched = 0 + def check(item): + try: + if get_item_uuid(item) in uuids: return 1 + except: pass + return 0 + try: + for lst in [board.GetTracks(), board.GetFootprints(), board.GetDrawings(), board.Zones()]: + for item in lst: matched += check(item) + except: pass + self.log(f"Analyze: Total Matches on Board: {matched}") + return self.get_log_text() + + def recover_orphans(self): + if not self.storage.setup_paths(): return 0, "Storage not ready" + tracked_uuids = set() + stored_files = set() + board = pcbnew.GetBoard() + for l in self.layers: + for f in l.stored_items: stored_files.add(f) + for entry in l.on_board_items: tracked_uuids.add(entry['uuid']) + orphans = [] + try: + for f in os.listdir(self.storage.session_dir): + if f.endswith(".json") and f != "$Master$.json" and f not in stored_files: + data = self.storage.load_item(f) + if not data or 'uuid' not in data: continue + uuid = data['uuid'] + if uuid in tracked_uuids or find_item_by_uuid(board, uuid): continue + orphans.append(f) + except Exception as e: return 0, f"Error scanning dir: {e}" + if not orphans: return 0, "No orphans found" + rec_layer = self.create_layer("Recovered") + rec_layer.stored_items = orphans + rec_layer.visible = False + self.save() + return len(orphans), f"Recovered {len(orphans)} items." + + def hard_refresh(self): + self.log("Hard Refresh: Starting...") + board = pcbnew.GetBoard() + for layer in self.layers: + if layer.visible: + valid_on_board = [] + for entry in layer.on_board_items: + uuid = entry['uuid'] + item = find_item_by_uuid(board, uuid) + if item: + sexpr, err = Serializer.serialize(item) + if sexpr: valid_on_board.append(entry) + else: + self.log(f"Refresh: Item {uuid} missing from visible layer {layer.name}") + layer.on_board_items = valid_on_board + else: + for filename in layer.stored_items: + data = self.storage.load_item(filename) + if data and 'uuid' in data: + uuid = data['uuid'] + item = find_item_by_uuid(board, uuid) + if item: + self.log(f"Refresh: Found ghost {uuid} from hidden layer {layer.name}. Removing.") + try: board.Remove(item) + except: pass + self.save() + self.log("Hard Refresh: Complete") + +manager = LayerManager() + + +====================================================================== +// File: serializer.py +====================================================================== + +# backend/serializer.py +import pcbnew + +class Serializer: + @staticmethod + def serialize(item): + """ + Returns (sexpr_string, error_message). + """ + if not item: return None, "Item is None" + + last_error = "" + + # Method 1: PCB_IO_KICAD_SEXPR (Robust, KiCad 6+) + try: + sf = pcbnew.STRING_FORMATTER() + plugin = pcbnew.PCB_IO_KICAD_SEXPR() + plugin.SetOutputFormatter(sf) + plugin.Format(item) + res = sf.GetString() + if res and len(res) > 0: + return res, None + else: + last_error = "Format returned empty string" + except Exception as e: + last_error = str(e) + + # Method 2: Fallback to direct Serialize + try: + sf = pcbnew.STRING_FORMATTER() + if hasattr(item, 'Serialize'): + item.Serialize(sf) + res = sf.GetString() + if res and len(res) > 0: + return res, None + except Exception as e: + last_error = f"{last_error} | Fallback: {str(e)}" + + return None, last_error + + @staticmethod + def deserialize(data, board): + """ + Returns (item, error_message). + """ + if not data: return None, "No data provided" + cls_name = data.get('class') + sexpr = data.get('sexpr') + if not cls_name or not sexpr: return None, "Missing class or sexpr" + + try: + if not hasattr(pcbnew, cls_name): + return None, f"Class {cls_name} not found in pcbnew" + + cls = getattr(pcbnew, cls_name) + item = None + + # Instantiate item + try: + item = cls(board) + except: + try: + item = cls() + except Exception as e: + return None, f"Constructor failed for {cls_name}: {e}" + + # Deserialize with KiCad version compatibility + # KiCad 9+ requires (data, source_name), older versions take (data) + try: + lr = pcbnew.STRING_LINE_READER(sexpr, "restore") + except: + try: + lr = pcbnew.STRING_LINE_READER(sexpr) + except Exception as e: + return None, f"STRING_LINE_READER init failed: {e}" + + item.Deserialize(lr) + return item, None + except Exception as e: + return None, f"Deserialization error for {cls_name}: {e}" + + diff --git a/backend/resolvers.py b/backend/resolvers.py new file mode 100644 index 0000000..1f28747 --- /dev/null +++ b/backend/resolvers.py @@ -0,0 +1,112 @@ +# backend/resolvers.py +import pcbnew + +def get_item_uuid(item): + """ + Robustly retrieve the UUID string from a KiCad item. + Prioritizes m_Uuid property (KiCad 9 SWIG) over GetKIID(). + """ + if not item: return None + try: + # KiCad 9 / SWIG property access + if hasattr(item, 'm_Uuid'): + return item.m_Uuid.AsString() + # Legacy / Alternative accessor + if hasattr(item, 'GetKIID'): + return item.GetKIID().AsString() + except: + pass + return None + +def resolve_to_trackable_item(item): + """ + Resolves an item to the actual object we want to track. + - If item is a Pad/Text/Shape inside a Footprint -> Returns the Footprint. + - If item is a Group -> Returns None (we track contents, not groups). + - Otherwise -> Returns the item itself. + """ + if not item: return None + + cls = item.GetClass() + if cls == "PCB_GROUP": + return None + + # Check for Parent (e.g. Pad -> Footprint) + parent = item.GetParent() + if parent and parent.GetClass() == "FOOTPRINT": + return parent + + return item + +def cast_item(item): + """ + Casts a generic BOARD_ITEM to its specific class type. + Required for methods like Serialize or Format to work correctly. + """ + if not item: return None + + # Try generic Cast() first (Available on some BOARD_ITEM wrappers) + if hasattr(item, 'Cast'): + try: + return item.Cast() + except: + pass + + # Fallback to manual casting based on class name + cls = item.GetClass() + try: + if cls == "FOOTPRINT": return pcbnew.Cast_to_FOOTPRINT(item) + if cls == "PCB_TRACK": return pcbnew.Cast_to_PCB_TRACK(item) + if cls == "PCB_VIA": return pcbnew.Cast_to_PCB_VIA(item) + if cls == "PCB_ARC": return pcbnew.Cast_to_PCB_ARC(item) + if cls == "PCB_SHAPE": return pcbnew.Cast_to_PCB_SHAPE(item) + if cls == "PCB_TEXT": return pcbnew.Cast_to_PCB_TEXT(item) + if cls == "PCB_TEXTBOX": return pcbnew.Cast_to_PCB_TEXTBOX(item) + if cls == "ZONE": return pcbnew.Cast_to_ZONE(item) + if cls == "PCB_GROUP": return pcbnew.Cast_to_PCB_GROUP(item) + if cls == "PCB_TARGET": return pcbnew.Cast_to_PCB_TARGET(item) + if cls == "PCB_DIM_ALIGNED": return pcbnew.Cast_to_PCB_DIM_ALIGNED(item) + if cls == "PCB_DIM_ORTHOGONAL": return pcbnew.Cast_to_PCB_DIM_ORTHOGONAL(item) + if cls == "PCB_DIM_CENTER": return pcbnew.Cast_to_PCB_DIM_CENTER(item) + if cls == "PCB_DIM_LEADER": return pcbnew.Cast_to_PCB_DIM_LEADER(item) + if cls == "PCB_DIM_RADIAL": return pcbnew.Cast_to_PCB_DIM_RADIAL(item) + except: + pass + + return item + +def find_item_by_uuid(board, uuid): + """ + Locates an item on the board by its UUID string. + Checks standard lists (Tracks, Footprints, Drawings, Zones). + Returns a CAST item (specific type) if found. + """ + item = None + if hasattr(board, 'GetItem'): + try: + item = board.GetItem(pcbnew.KIID(uuid)) + except: pass + + if not item: + # Fallback lists for older API or if GetItem fails + lists = [] + try: lists.append(board.GetTracks()) + except: pass + try: lists.append(board.GetFootprints()) + except: pass + try: lists.append(board.GetDrawings()) + except: pass + try: lists.append(board.Zones()) + except: pass + + for lst in lists: + for candidate in lst: + if get_item_uuid(candidate) == uuid: + item = candidate + break + if item: break + + if item: + return cast_item(item) + + return None \ No newline at end of file diff --git a/backend/serializer.py b/backend/serializer.py new file mode 100644 index 0000000..af2010d --- /dev/null +++ b/backend/serializer.py @@ -0,0 +1,80 @@ +# backend/serializer.py +import pcbnew + +class Serializer: + @staticmethod + def serialize(item): + """ + Returns (sexpr_string, error_message). + """ + if not item: return None, "Item is None" + + last_error = "" + + # Method 1: PCB_IO_KICAD_SEXPR (Robust, KiCad 6+) + try: + sf = pcbnew.STRING_FORMATTER() + plugin = pcbnew.PCB_IO_KICAD_SEXPR() + plugin.SetOutputFormatter(sf) + plugin.Format(item) + res = sf.GetString() + if res and len(res) > 0: + return res, None + else: + last_error = "Format returned empty string" + except Exception as e: + last_error = str(e) + + # Method 2: Fallback to direct Serialize + try: + sf = pcbnew.STRING_FORMATTER() + if hasattr(item, 'Serialize'): + item.Serialize(sf) + res = sf.GetString() + if res and len(res) > 0: + return res, None + except Exception as e: + last_error = f"{last_error} | Fallback: {str(e)}" + + return None, last_error + + @staticmethod + def deserialize(data, board): + """ + Returns (item, error_message). + """ + if not data: return None, "No data provided" + cls_name = data.get('class') + sexpr = data.get('sexpr') + if not cls_name or not sexpr: return None, "Missing class or sexpr" + + try: + if not hasattr(pcbnew, cls_name): + return None, f"Class {cls_name} not found in pcbnew" + + cls = getattr(pcbnew, cls_name) + item = None + + # Instantiate item + try: + item = cls(board) + except: + try: + item = cls() + except Exception as e: + return None, f"Constructor failed for {cls_name}: {e}" + + # Deserialize with KiCad version compatibility + # KiCad 9+ requires (data, source_name), older versions take (data) + try: + lr = pcbnew.STRING_LINE_READER(sexpr, "restore") + except: + try: + lr = pcbnew.STRING_LINE_READER(sexpr) + except Exception as e: + return None, f"STRING_LINE_READER init failed: {e}" + + item.Deserialize(lr) + return item, None + except Exception as e: + return None, f"Deserialization error for {cls_name}: {e}" \ No newline at end of file diff --git a/backend/storage.py b/backend/storage.py new file mode 100644 index 0000000..4d77375 --- /dev/null +++ b/backend/storage.py @@ -0,0 +1,134 @@ +# backend/storage.py +import os +import json +import time +import datetime +import pcbnew + +class StorageManager: + def __init__(self): + self.project_dir = "" + self.session_dir = "" + self.layers_dir = "" + self.master_file = "" + + def _get_board_path(self): + try: + board = pcbnew.GetBoard() + return board.GetFileName() + except: + return "" + + def setup_paths(self): + board_path = self._get_board_path() + if not board_path: return False + + self.project_dir = os.path.dirname(board_path) + filename = os.path.basename(board_path) + schematic_name = os.path.splitext(filename)[0] + + try: + mtime = os.path.getmtime(board_path) + ts_str = str(int(mtime)) + except: + ts_str = str(int(time.time())) + + date_str = datetime.datetime.fromtimestamp(mtime).strftime("%b_%d") + + session_name = f"{schematic_name}_{ts_str}_{date_str}" + self.session_dir = os.path.join(self.project_dir, session_name) + self.layers_dir = os.path.join(self.session_dir, "logical_layers") + self.master_file = os.path.join(self.layers_dir, "$Master$.json") + + if not os.path.exists(self.layers_dir): + try: + os.makedirs(self.layers_dir) + except OSError as e: + print(f"Storage: Failed to create dirs: {e}") + return False + + return True + + def save_item(self, item_data, uuid=None): + if not self.session_dir: self.setup_paths() + + cls = item_data.get('class', 'Item') + ref = item_data.get('ref', '') + net = item_data.get('net', '') + + name_part = ref if ref else (net if net else cls) + name_part = "".join(c for c in name_part if c.isalnum() or c in ('_', '-')) + + suffix = uuid[:8] if uuid else "unknown" + filename = f"{name_part}_{suffix}.json" + + filepath = os.path.join(self.session_dir, filename) + + try: + with open(filepath, 'w') as f: + json.dump(item_data, f, indent=2) + return filename + except Exception as e: + print(f"Storage: Error saving item {filename}: {e}") + return None + + def save_layer(self, layer_name, layer_data): + if not self.session_dir: self.setup_paths() + + filename = f"{layer_name}.json" + filepath = os.path.join(self.layers_dir, filename) + + try: + with open(filepath, 'w') as f: + json.dump(layer_data, f, indent=2) + return filename + except Exception as e: + print(f"Storage: Error saving layer {layer_name}: {e}") + return None + + def update_master(self, layers_list): + if not self.session_dir: self.setup_paths() + + master_data = { + "updated": time.time(), + "layers": [] + } + + for l in layers_list: + master_data["layers"].append({ + "name": l.name, + "visible": l.visible, + "item_count": len(l.on_board_items) if l.visible else len(l.stored_items), + "file": f"{l.name}.json" + }) + + try: + with open(self.master_file, 'w') as f: + json.dump(master_data, f, indent=2) + except Exception as e: + print(f"Storage: Error updating Master: {e}") + + def load_master(self): + if not self.session_dir: self.setup_paths() + if os.path.exists(self.master_file): + try: + with open(self.master_file, 'r') as f: + return json.load(f) + except: pass + return None + + def load_layer(self, layer_name): + if not self.session_dir: self.setup_paths() + filepath = os.path.join(self.layers_dir, f"{layer_name}.json") + if os.path.exists(filepath): + with open(filepath, 'r') as f: + return json.load(f) + return None + + def load_item(self, filename): + if not self.session_dir: self.setup_paths() + filepath = os.path.join(self.session_dir, filename) + if os.path.exists(filepath): + with open(filepath, 'r') as f: + return json.load(f) + return None \ No newline at end of file diff --git a/backend/thumbnails.py b/backend/thumbnails.py new file mode 100644 index 0000000..adb88fd --- /dev/null +++ b/backend/thumbnails.py @@ -0,0 +1,89 @@ +# backend/thumbnails.py +import wx +import pcbnew +from .resolvers import find_item_by_uuid + +class ThumbnailGenerator: + @staticmethod + def generate_thumbnail(item_list, board, width=80, height=40): + """ + Generates a simple preview bitmap of the items. + """ + bmp = wx.Bitmap(width, height) + dc = wx.MemoryDC(bmp) + + # Background + dc.SetBackground(wx.Brush(wx.Colour(30, 30, 30))) + dc.Clear() + + # Collect items + items = [] + min_x, min_y = float('inf'), float('inf') + max_x, max_y = float('-inf'), float('-inf') + has_items = False + + for entry in item_list: + uuid = entry['uuid'] + item = find_item_by_uuid(board, uuid) + if item: + items.append(item) + bb = item.GetBoundingBox() + min_x = min(min_x, bb.GetX()) + min_y = min(min_y, bb.GetY()) + max_x = max(max_x, bb.GetRight()) + max_y = max(max_y, bb.GetBottom()) + has_items = True + + if has_items: + content_w = max_x - min_x + content_h = max_y - min_y + if content_w == 0: content_w = 1 + if content_h == 0: content_h = 1 + + # Scale to fit in width x height with some padding + scale_x = (width * 0.9) / content_w + scale_y = (height * 0.9) / content_h + scale = min(scale_x, scale_y) + + off_x = (width - (content_w * scale)) / 2 + off_y = (height - (content_h * scale)) / 2 + + pen_track = wx.Pen(wx.Colour(0, 200, 0), 1) + brush_pad = wx.Brush(wx.Colour(200, 0, 0)) + pen_pad = wx.Pen(wx.Colour(200, 0, 0), 1) + + for item in items: + cls = item.GetClass() + if cls == "PCB_TRACK": + dc.SetPen(pen_track) + t = pcbnew.Cast_to_PCB_TRACK(item) + start = t.GetStart() + end = t.GetEnd() + x1 = int((start.x - min_x) * scale + off_x) + y1 = int((start.y - min_y) * scale + off_y) + x2 = int((end.x - min_x) * scale + off_x) + y2 = int((end.y - min_y) * scale + off_y) + dc.DrawLine(x1, y1, x2, y2) + elif cls == "PCB_VIA": + dc.SetPen(pen_track) + dc.SetBrush(wx.Brush(wx.Colour(200, 200, 0))) + v = pcbnew.Cast_to_PCB_VIA(item) + pos = v.GetPosition() + x = int((pos.x - min_x) * scale + off_x) + y = int((pos.y - min_y) * scale + off_y) + r = max(1, int((v.GetWidth() / 2) * scale)) + dc.DrawCircle(x, y, r) + else: + dc.SetPen(pen_pad) + dc.SetBrush(brush_pad) + bb = item.GetBoundingBox() + x = int((bb.GetX() - min_x) * scale + off_x) + y = int((bb.GetY() - min_y) * scale + off_y) + w = int(bb.GetWidth() * scale) + h = int(bb.GetHeight() * scale) + if w < 2: w = 2 + if h < 2: h = 2 + dc.DrawRectangle(x, y, w, h) + + dc.SelectObject(wx.NullBitmap) + return bmp \ No newline at end of file diff --git a/debug.py b/debug.py new file mode 100644 index 0000000..92ffeff --- /dev/null +++ b/debug.py @@ -0,0 +1,87 @@ +# debug.py +import pcbnew +import sys + + +''' +Okay, this is for historical record, for others. I nearly cried trying +to figure out how to get anything to serialize +from a selection or even an item by ref i had (thought) i was directly pointing to... + +long story short, inheretance is not straightforward as it seems it ought to be. + +the only thing you can trust is the __dict__ of the selection or item in question, +however, this is just part of the stuff it really has... + +I have not found a clear way to tell what is going to get inheretence as expected. + +But here is how to begin. I tried all of these bananas and finally found a way to actually get-> then do( stuff ) with a selection. + +Hope it saves somebody some trouble. +''' + + +def debug_selection(): + try: + selection = pcbnew.GetCurrentSelection() + except Exception as e: + print(f"FAILED to call GetCurrentSelection(): {e}") + return + + raw_count = 0 + + print("iterating->...") + + try: + for item in selection: + raw_count += 1 + + print(f"\n[{raw_count}] selected:") + print(f"class: {item.GetClass()}") + print(f"type: {type(item)}") + print(f"mro: {type(item).mro()}") + + # Check for UUID methods + uuid_val = "NOT FOUND" + + # 1. Try GetKIID() (Standard) + if hasattr(item, 'GetKIID'): + try: + uuid_val = item.GetKIID().AsString() + print(f" Method: GetKIID() -> {uuid_val}") + except Exception as e: + print(f" Method: GetKIID() -> Error: {e}") + + ## This is the only one that works, for future reference to others... ## vvvvvvvvv + + # 2. Try m_Uuid (Property) vvvvvvvv + if hasattr(item, 'm_Uuid'): + try: + uuid_val = str(item.m_Uuid.AsString()) + print(f" Property: m_Uuid -> {uuid_val}") + except Exception as e: + print(f" Property: m_Uuid -> Error: {e}") + # ^^^^^^. ^yes this one^ ^^^^^^ + ######################################################################### ^^^^^^^^ + + # 3. Try GetUuid() (Alternative) + if hasattr(item, 'GetUuid'): + try: + uuid_val = item.GetUuid().AsString() + print(f" Method: GetUuid() -> {uuid_val}") + except Exception as e: + print(f" Method: GetUuid() -> Error: {e}") + + # 4. Try Cast() (Force cast to EDA_ITEM) + try: + eda_item = pcbnew.Cast_to_EDA_ITEM(item) + if hasattr(eda_item, 'GetKIID'): + print(f" Cast(EDA_ITEM).GetKIID() -> {eda_item.GetKIID().AsString()}") + except: + pass + + except Exception as e: + print(f"Error iterating selection: {e}") + + print("-" * 30) + print(f"Raw Selection Count: {raw_count}") \ No newline at end of file diff --git a/debug2.py b/debug2.py new file mode 100644 index 0000000..d530a7e --- /dev/null +++ b/debug2.py @@ -0,0 +1,236 @@ +# debug2.py +import pcbnew +import sys +import wx +import os +from .backend import manager +from .backend.resolvers import find_item_by_uuid, get_item_uuid + +def log(msg): + print(f"[DEBUG2] {msg}") + +def debug_dump_layer(layer_idx=0): + """Prints the internal state of a specific layer.""" + if layer_idx >= len(manager.layers): + log("Invalid layer index") + return + l = manager.layers[layer_idx] + log(f"Layer '{l.name}' (Visible: {l.visible})") + log(f" On Board Items: {len(l.on_board_items)}") + for item in l.on_board_items: + log(f" - {item['uuid']} ({item['class']})") + log(f" Stored Items: {len(l.stored_items)}") + for item in l.stored_items: + log(f" - {item}") + +def debug_check_item_state(item): + """Checks flags and state of an item.""" + if not item: + return "None" + + state = [] + try: + if item.IsSelected(): state.append("Selected") + if item.IsLocked(): state.append("Locked") + if item.GetParent(): state.append(f"HasParent({item.GetParent().GetClass()})") + except Exception as e: + state.append(f"ErrorChecking({e})") + + return ", ".join(state) + +def clear_selection_safe(): + """Safely clears selection by iterating selected items.""" + try: + sel = pcbnew.GetCurrentSelection() + items = [i for i in sel] + if not items: + return + + log(f" [ACTION] Clearing selection of {len(items)} items...") + for item in items: + if hasattr(item, 'ClearSelected'): + item.ClearSelected() + if hasattr(item, 'ClearBrightened'): + item.ClearBrightened() + except Exception as e: + log(f" [FAIL] Failed to clear selection: {e}") + +def serialize_item_safe(item): + """ + Attempts to serialize an item using PCB_IO_KICAD_SEXPR (Format). + """ + if not item: return None + + try: + sf = pcbnew.STRING_FORMATTER() + plugin = pcbnew.PCB_IO_KICAD_SEXPR() + plugin.SetOutputFormatter(sf) + plugin.Format(item) + return sf.GetString() + except Exception as e: + log(f" [WARN] Plugin serialization failed: {e}") + try: + sf = pcbnew.STRING_FORMATTER() + if hasattr(item, 'Serialize'): + item.Serialize(sf) + return sf.GetString() + except Exception as e2: + log(f" [FAIL] Direct serialization failed: {e2}") + return None + +def debug_test_hide(layer_idx=0): + """ + Performs a FULL hide operation with logging: + 1. Clear Selection + 2. Serialize & Save to Disk + 3. Remove from Board + 4. Update Layer State + """ + log("--- TEST HIDE START ---") + if layer_idx >= len(manager.layers): + log("Invalid layer index") + return + + layer = manager.layers[layer_idx] + board = pcbnew.GetBoard() + + # Ensure storage is ready + if not manager.storage.setup_paths(): + log("[FAIL] Could not setup storage paths") + return + + if not layer.visible: + log("Layer is already hidden. forcing visible=True for test logic (assuming items are on board).") + + log(f"Iterating {len(layer.on_board_items)} items to hide...") + + clear_selection_safe() + + new_stored_items = [] + items_to_remove = [] + + for i, entry in enumerate(layer.on_board_items): + uuid = entry['uuid'] + log(f"Item {i}: UUID {uuid}") + + item = find_item_by_uuid(board, uuid) + if item is None: + log(" [FAIL] Item not found on board") + continue + + # Serialize + sexpr = serialize_item_safe(item) + if not sexpr: + log(" [FAIL] Serialization failed") + continue + + # Save to disk + item_data = { + 'class': item.GetClass(), + 'sexpr': sexpr, + 'uuid': uuid + } + if hasattr(item, 'GetReference'): item_data['ref'] = item.GetReference() + if hasattr(item, 'GetNetname'): item_data['net'] = item.GetNetname() + + filename = manager.storage.save_item(item_data, uuid) + if filename: + log(f" [OK] Saved to {filename}") + new_stored_items.append(filename) + items_to_remove.append(item) + else: + log(" [FAIL] Failed to save file") + + # Remove items + log(f"Removing {len(items_to_remove)} items...") + for item in items_to_remove: + try: + if item.IsLocked(): item.SetLocked(False) + board.Remove(item) + except Exception as e: + log(f" [FAIL] Remove failed: {e}") + + # Update Layer State + layer.stored_items = new_stored_items + layer.on_board_items = [] + layer.visible = False + manager.save() + + pcbnew.Refresh() + log("--- TEST HIDE END ---") + +def debug_test_unhide(layer_idx=0): + """ + Performs a FULL unhide operation with logging: + 1. Load from Disk + 2. Deserialize + 3. Add to Board + 4. Update Layer State + """ + log("--- TEST UNHIDE START ---") + if layer_idx >= len(manager.layers): + log("Invalid layer index") + return + + layer = manager.layers[layer_idx] + board = pcbnew.GetBoard() + + if layer.visible: + log("Layer is visible. Forcing visible=False for test logic.") + + log(f"Iterating {len(layer.stored_items)} stored items to restore...") + + new_on_board = [] + + for filename in layer.stored_items: + log(f"Loading {filename}...") + item_data = manager.storage.load_item(filename) + if not item_data: + log(" [FAIL] Load failed") + continue + + cls_name = item_data.get('class') + sexpr = item_data.get('sexpr') + uuid = item_data.get('uuid') + + if not hasattr(pcbnew, cls_name): + log(f" [FAIL] Unknown class {cls_name}") + continue + + try: + cls = getattr(pcbnew, cls_name) + try: item = cls(board) + except: item = cls() + + # Fix: STRING_LINE_READER requires 2 arguments in KiCad 9 (data, source_name) + lr = pcbnew.STRING_LINE_READER(sexpr, "restore") + item.Deserialize(lr) + + board.Add(item) + + # Re-verify UUID + new_uuid = get_item_uuid(item) + log(f" [OK] Restored item {new_uuid}") + new_on_board.append({'uuid': new_uuid, 'class': cls_name}) + + except Exception as e: + log(f" [FAIL] Restore failed: {e}") + + # Update Layer State + layer.on_board_items = new_on_board + layer.stored_items = [] + layer.visible = True + manager.save() + + pcbnew.Refresh() + log("--- TEST UNHIDE END ---") + +def debug_reset_state(layer_idx=0): + """Resets a layer to 'Visible' and empty, useful if state gets desynced.""" + if layer_idx >= len(manager.layers): return + l = manager.layers[layer_idx] + l.visible = True + l.on_board_items = [] + l.stored_items = [] + manager.save() + log(f"Layer {l.name} state reset to Visible/Empty.") \ No newline at end of file diff --git a/interface.py b/interface.py new file mode 100644 index 0000000..adb7cbf --- /dev/null +++ b/interface.py @@ -0,0 +1,561 @@ +# interface.py +import wx +import wx.dataview as dv +import pcbnew +from .backend import manager +from .backend.thumbnails import ThumbnailGenerator + +class LogDialog(wx.Dialog): + def __init__(self, parent, title, log_text): + super().__init__(parent, title=title, size=(600, 400), style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER) + sizer = wx.BoxSizer(wx.VERTICAL) + text = wx.TextCtrl(self, style=wx.TE_MULTILINE | wx.TE_READONLY | wx.HSCROLL) + text.SetValue(log_text) + sizer.Add(text, 1, wx.EXPAND | wx.ALL, 10) + btn = wx.Button(self, wx.ID_OK, "Close") + sizer.Add(btn, 0, wx.ALIGN_CENTER | wx.BOTTOM, 10) + self.SetSizer(sizer) + btn.Bind(wx.EVT_BUTTON, lambda e: self.EndModal(wx.ID_OK)) + +class DeleteDialog(wx.Dialog): + def __init__(self, parent): + super().__init__(parent, title="Delete Layer", size=(400, 200)) + sizer = wx.BoxSizer(wx.VERTICAL) + lbl = wx.StaticText(self, label="How should items associated with this layer be handled?") + sizer.Add(lbl, 0, wx.ALL, 15) + self.cb_remember = wx.CheckBox(self, label="Remember my choice (Don't ask again)") + sizer.Add(self.cb_remember, 0, wx.LEFT | wx.RIGHT | wx.BOTTOM, 15) + btn_sizer = wx.BoxSizer(wx.HORIZONTAL) + btn_del_all = wx.Button(self, id=wx.ID_YES, label="Delete Layer & Items") + btn_del_layer = wx.Button(self, id=wx.ID_NO, label="Delete Layer Only") + btn_cancel = wx.Button(self, id=wx.ID_CANCEL, label="Cancel") + btn_sizer.Add(btn_del_all, 0, wx.ALL, 5) + btn_sizer.Add(btn_del_layer, 0, wx.ALL, 5) + btn_sizer.Add(btn_cancel, 0, wx.ALL, 5) + sizer.Add(btn_sizer, 0, wx.ALIGN_CENTER | wx.ALL, 10) + self.SetSizer(sizer) + self.Fit() + btn_del_all.Bind(wx.EVT_BUTTON, self.OnButton) + btn_del_layer.Bind(wx.EVT_BUTTON, self.OnButton) + btn_cancel.Bind(wx.EVT_BUTTON, self.OnButton) + + def OnButton(self, event): + self.EndModal(event.GetId()) + +class LayerDropTarget(wx.TextDropTarget): + def __init__(self, panel): + super().__init__() + self.panel = panel + + def OnDragOver(self, x, y, defResult): + # Provide visual feedback by selecting the row under the cursor + item, col = self.panel.list.HitTest(wx.Point(x, y)) + if item.IsOk(): + row = self.panel.list.ItemToRow(item) + self.panel.list.SelectRow(row) + return defResult + + def OnDropText(self, x, y, data): + try: + source_idx = int(data) + item, col = self.panel.list.HitTest(wx.Point(x, y)) + + if not item.IsOk(): + target_idx = self.panel.list.GetItemCount() + else: + target_idx = self.panel.list.ItemToRow(item) + + if source_idx != target_idx: + # Capture active layer object to restore selection index later + active_layer = None + if manager.active_layer_index is not None and 0 <= manager.active_layer_index < len(manager.layers): + active_layer = manager.layers[manager.active_layer_index] + + # Perform the move + if 0 <= source_idx < len(manager.layers): + layer_obj = manager.layers.pop(source_idx) + + # Adjust target if we removed an item before it + if source_idx < target_idx: + target_idx -= 1 + + # Clamp + if target_idx < 0: target_idx = 0 + if target_idx > len(manager.layers): target_idx = len(manager.layers) + + manager.layers.insert(target_idx, layer_obj) + + # Restore active layer index + if active_layer: + try: + manager.active_layer_index = manager.layers.index(active_layer) + except ValueError: + manager.active_layer_index = None + + manager.save() + self.panel.RefreshList() + self.panel.list.SelectRow(target_idx) + return True + except Exception as e: + print(f"Drop Error: {e}") + return False + +class LayerPanel(wx.Panel): + def __init__(self, parent): + super().__init__(parent) + + sizer = wx.BoxSizer(wx.VERTICAL) + + # Toolbar + btn_sizer = wx.BoxSizer(wx.HORIZONTAL) + self.btn_new = wx.Button(self, label="New") + self.btn_add = wx.Button(self, label="Add") + self.btn_paste = wx.Button(self, label="Paste") + self.btn_del = wx.Button(self, label="Del") + self.btn_settings = wx.Button(self, label="âš™", size=(30, 24)) + + btn_sizer.Add(self.btn_new, 0, wx.ALL, 2) + btn_sizer.Add(self.btn_add, 0, wx.ALL, 2) + btn_sizer.Add(self.btn_paste, 0, wx.ALL, 2) + btn_sizer.Add(self.btn_del, 0, wx.ALL, 2) + btn_sizer.Add(self.btn_settings, 0, wx.ALL, 2) + + # Sort Toolbar + sort_sizer = wx.BoxSizer(wx.HORIZONTAL) + self.btn_up = wx.Button(self, label="â–²", size=(30, 24)) + self.btn_down = wx.Button(self, label="â–¼", size=(30, 24)) + sort_sizer.Add(self.btn_up, 0, wx.ALL, 2) + sort_sizer.Add(self.btn_down, 0, wx.ALL, 2) + + # DataViewListCtrl + # Use DV_ROW_LINES for row separators + self.list = dv.DataViewListCtrl(self, style=wx.BORDER_THEME | dv.DV_ROW_LINES) + + # Columns: Active (Toggle), Visible (Toggle), Preview (IconText), Name (Text), Items (Text) + self.col_active = self.list.AppendToggleColumn("Act", width=35) + self.col_vis = self.list.AppendToggleColumn("Vis", width=35) + # Use IconTextColumn for preview to avoid AppendBitmapColumn issues + self.col_thumb = self.list.AppendIconTextColumn("Preview", width=85, mode=dv.DATAVIEW_CELL_INERT) + self.col_name = self.list.AppendTextColumn("Name", width=150, mode=dv.DATAVIEW_CELL_EDITABLE) + self.col_items = self.list.AppendTextColumn("Items", width=50) + + # Drag and Drop + self.drop_target = LayerDropTarget(self) + self.list.SetDropTarget(self.drop_target) + + sizer.Add(btn_sizer, 0, wx.EXPAND) + sizer.Add(sort_sizer, 0, wx.EXPAND) + sizer.Add(self.list, 1, wx.EXPAND) + self.SetSizer(sizer) + + # Bindings + self.Bind(wx.EVT_BUTTON, self.OnNew, self.btn_new) + self.Bind(wx.EVT_BUTTON, self.OnAddSel, self.btn_add) + self.Bind(wx.EVT_BUTTON, self.OnPasteSel, self.btn_paste) + self.Bind(wx.EVT_BUTTON, self.OnDelete, self.btn_del) + self.Bind(wx.EVT_BUTTON, self.OnSettings, self.btn_settings) + self.Bind(wx.EVT_BUTTON, self.OnUp, self.btn_up) + self.Bind(wx.EVT_BUTTON, self.OnDown, self.btn_down) + + self.list.Bind(dv.EVT_DATAVIEW_ITEM_VALUE_CHANGED, self.OnValueChanged) + self.list.Bind(dv.EVT_DATAVIEW_ITEM_EDITING_DONE, self.OnRenameDone) + self.list.Bind(dv.EVT_DATAVIEW_ITEM_CONTEXT_MENU, self.OnContextMenu) + self.list.Bind(dv.EVT_DATAVIEW_ITEM_BEGIN_DRAG, self.OnBeginDrag) + + def RefreshList(self): + self.list.DeleteAllItems() + board = pcbnew.GetBoard() + + for i, l in enumerate(manager.layers): + is_active = (manager.active_layer_index == i) + is_visible = l.visible + + # Generate thumbnail + items_to_draw = l.on_board_items if l.visible else [] + bmp = ThumbnailGenerator.generate_thumbnail(items_to_draw, board, 80, 40) + + # Convert Bitmap to Icon for DataViewIconText + icon = wx.Icon() + icon.CopyFromBitmap(bmp) + preview_data = dv.DataViewIconText("", icon) + + count_str = str(len(l.on_board_items) if l.visible else len(l.stored_items)) + + # Append [Active, Visible, IconText, Name, Count] + self.list.AppendItem([is_active, is_visible, preview_data, l.name, count_str]) + + # Force UI update + self.list.Refresh() + self.list.Update() + + def OnValueChanged(self, event): + col = event.GetColumn() + item = event.GetItem() + if not item.IsOk(): return + + row = self.list.ItemToRow(item) + if row < 0 or row >= len(manager.layers): return + + layer = manager.layers[row] + + # Column 0: Active + if col == 0: + # This is a radio-like behavior. + # The event has already toggled the value in the model, but we need to enforce single selection. + is_checked = self.list.GetToggleValue(row, 0) + + if is_checked: + manager.set_active_layer(row) + # Uncheck others + for r in range(self.list.GetItemCount()): + if r != row: + self.list.SetToggleValue(False, r, 0) + else: + # If user unchecks the active layer, we have no active layer + if manager.active_layer_index == row: + manager.set_active_layer(None) + + # Refresh list to update thumbnails if needed (active layer might be drawn differently) + wx.CallAfter(self.RefreshList) + + # Column 1: Visible + elif col == 1: + is_visible = self.list.GetToggleValue(row, 1) + # Use CallAfter to decouple heavy logic from event handler + wx.CallAfter(self.DoToggleVis, row, is_visible) + + def DoToggleVis(self, row, is_visible): + layer = manager.layers[row] + + manager.clear_log() + + if is_visible and not layer.visible: + layer.show() + elif not is_visible and layer.visible: + layer.hide() + + pcbnew.Refresh() + self.RefreshList() + + # Check if state matches intent + if layer.visible != is_visible: + # State mismatch! Show log. + dlg = LogDialog(self, "Layer Toggle Error", manager.get_log_text()) + dlg.ShowModal() + dlg.Destroy() + + def OnRenameDone(self, event): + item = event.GetItem() + if not item.IsOk(): return + row = self.list.ItemToRow(item) + + # Use CallAfter to ensure the model has updated the text value + wx.CallAfter(self._SaveRename, row) + + def _SaveRename(self, row): + if 0 <= row < len(manager.layers): + new_name = self.list.GetTextValue(row, 3) + manager.layers[row].name = new_name + manager.save() + + def OnBeginDrag(self, event): + item = event.GetItem() + if not item.IsOk(): return + + row = self.list.ItemToRow(item) + + # Create drag source + source = wx.DropSource(self.list) + data = wx.TextDataObject(str(row)) + source.SetData(data) + source.DoDragDrop(wx.Drag_DefaultMove) + + def OnNew(self, event): + dlg = wx.TextEntryDialog(self, "Layer Name:", "New Layer") + if dlg.ShowModal() == wx.ID_OK: + manager.create_layer(dlg.GetValue()) + self.RefreshList() + dlg.Destroy() + + def OnAddSel(self, event): + row = self.list.GetSelectedRow() + if row == -1: return + layer = manager.layers[row] + if not layer.visible: + wx.MessageBox("Unhide layer first.") + return + + manager.clear_log() + count, msg = layer.add_selection() + + if count == 0: + dlg = LogDialog(self, "Add Selection Log", manager.get_log_text()) + dlg.ShowModal() + dlg.Destroy() + else: + wx.MessageBox(msg) + + self.RefreshList() + + def GetClipboardText(self): + text = "" + if wx.TheClipboard.Open(): + try: + if wx.TheClipboard.IsSupported(wx.DataFormat(wx.DF_TEXT)): + data = wx.TextDataObject() + if wx.TheClipboard.GetData(data): + text = data.GetText() + except: pass + finally: + wx.TheClipboard.Close() + return text + + def OnPasteSel(self, event): + row = self.list.GetSelectedRow() + if row == -1: return + layer = manager.layers[row] + if not layer.visible: + wx.MessageBox("Unhide layer first.") + return + + manager.clear_log() + text = self.GetClipboardText() + if not text: + wx.MessageBox("Clipboard empty or invalid.") + else: + count, msg = layer.add_from_text(text) + if count == 0: + dlg = LogDialog(self, "Paste Log", manager.get_log_text()) + dlg.ShowModal() + dlg.Destroy() + else: + wx.MessageBox(msg) + + self.RefreshList() + + def OnDelete(self, event): + row = self.list.GetSelectedRow() + if row == -1: return + + mode = manager.settings.get("delete_mode", "ask") + delete_items = False + + if mode == "ask": + dlg = DeleteDialog(self) + res = dlg.ShowModal() + remember = dlg.cb_remember.GetValue() + dlg.Destroy() + if res == wx.ID_CANCEL: return + delete_items = (res == wx.ID_YES) + if remember: + manager.settings["delete_mode"] = "delete" if delete_items else "keep" + manager.save() + elif mode == "delete": + delete_items = True + elif mode == "keep": + delete_items = False + + manager.delete_layer(row, delete_items) + self.RefreshList() + + def OnUp(self, event): + row = self.list.GetSelectedRow() + if row == -1: return + if manager.move_layer_up(row): + self.RefreshList() + self.list.SelectRow(row - 1) + + def OnDown(self, event): + row = self.list.GetSelectedRow() + if row == -1: return + if manager.move_layer_down(row): + self.RefreshList() + self.list.SelectRow(row + 1) + + def OnSettings(self, event): + menu = wx.Menu() + menu.Append(wx.ID_ANY, "Deletion Behavior:", kind=wx.ITEM_NORMAL).Enable(False) + + cur_mode = manager.settings.get("delete_mode", "ask") + id_ask = wx.NewIdRef() + id_del = wx.NewIdRef() + id_keep = wx.NewIdRef() + + mi_ask = menu.AppendRadioItem(id_ask, "Ask every time") + mi_del = menu.AppendRadioItem(id_del, "Always Delete Items") + mi_keep = menu.AppendRadioItem(id_keep, "Always Keep Items") + + if cur_mode == "delete": mi_del.Check() + elif cur_mode == "keep": mi_keep.Check() + else: mi_ask.Check() + + menu.AppendSeparator() + id_analyze = wx.NewIdRef() + menu.Append(id_analyze, "Analyze Clipboard") + id_debug = wx.NewIdRef() + menu.Append(id_debug, "Show Debug Info") + + menu.AppendSeparator() + id_recover = wx.NewIdRef() + menu.Append(id_recover, "Recover Lost Items") + + self.Bind(wx.EVT_MENU, lambda e: self.SetMode("ask"), id=id_ask) + self.Bind(wx.EVT_MENU, lambda e: self.SetMode("delete"), id=id_del) + self.Bind(wx.EVT_MENU, lambda e: self.SetMode("keep"), id=id_keep) + self.Bind(wx.EVT_MENU, self.OnAnalyze, id=id_analyze) + self.Bind(wx.EVT_MENU, self.OnDebug, id=id_debug) + self.Bind(wx.EVT_MENU, self.OnRecover, id=id_recover) + + self.PopupMenu(menu) + menu.Destroy() + + def SetMode(self, mode): + manager.settings["delete_mode"] = mode + manager.save() + + def OnAnalyze(self, event): + manager.clear_log() + text = self.GetClipboardText() + if text: manager.analyze_clipboard_text(text) + dlg = LogDialog(self, "Analysis Log", manager.get_log_text()) + dlg.ShowModal() + dlg.Destroy() + + def OnDebug(self, event): + # Show full log in LogDialog + dlg = LogDialog(self, "Debug Info", manager.get_log_text()) + dlg.ShowModal() + dlg.Destroy() + + def OnRecover(self, event): + count, msg = manager.recover_orphans() + wx.MessageBox(msg, "Recovery Result") + self.RefreshList() + + def OnContextMenu(self, event): + item = event.GetItem() + if not item.IsOk(): return + + row = self.list.ItemToRow(item) + self.list.SelectRow(row) + + layer = manager.layers[row] + menu = wx.Menu() + + is_active = (manager.active_layer_index == row) + lbl_active = "Deactivate" if is_active else "Set Active" + item_act = menu.Append(wx.ID_ANY, lbl_active) + + lbl_vis = "Hide Layer" if layer.visible else "Show Layer" + item_vis = menu.Append(wx.ID_ANY, lbl_vis) + + menu.AppendSeparator() + + item_add = menu.Append(wx.ID_ANY, "Add Selection") + item_paste = menu.Append(wx.ID_ANY, "Add from Clipboard") + item_rem = menu.Append(wx.ID_ANY, "Remove Selection") + item_insp = menu.Append(wx.ID_ANY, "Inspect Content") + menu.AppendSeparator() + + item_del_all = menu.Append(wx.ID_ANY, "Delete Layer & Items") + item_del_keep = menu.Append(wx.ID_ANY, "Delete Layer (Keep Items)") + item_clr = menu.Append(wx.ID_ANY, "Clear Items (Keep Layer)") + + self.Bind(wx.EVT_MENU, lambda e: self.ToggleActive(row), item_act) + self.Bind(wx.EVT_MENU, lambda e: self.ToggleLayerVis(row), item_vis) + self.Bind(wx.EVT_MENU, lambda e: self.OnAddSel(None), item_add) + self.Bind(wx.EVT_MENU, lambda e: self.OnPasteSel(None), item_paste) + self.Bind(wx.EVT_MENU, lambda e: self.OnRemSel(row), item_rem) + self.Bind(wx.EVT_MENU, lambda e: self.OnInspect(row), item_insp) + self.Bind(wx.EVT_MENU, lambda e: self.DoDelete(row, True), item_del_all) + self.Bind(wx.EVT_MENU, lambda e: self.DoDelete(row, False), item_del_keep) + self.Bind(wx.EVT_MENU, lambda e: self.DoClear(row), item_clr) + + self.PopupMenu(menu) + menu.Destroy() + + def ToggleActive(self, row): + if manager.active_layer_index == row: + manager.set_active_layer(None) + self.list.SetToggleValue(False, row, 0) + else: + manager.set_active_layer(row) + for r in range(self.list.GetItemCount()): + self.list.SetToggleValue(r == row, r, 0) + self.RefreshList() + + def ToggleLayerVis(self, row): + # Use CallAfter to decouple heavy logic from event handler + wx.CallAfter(self._ToggleLayerVisImpl, row) + + def _ToggleLayerVisImpl(self, row): + layer = manager.layers[row] + if layer.visible: layer.hide() + else: layer.show() + pcbnew.Refresh() + self.RefreshList() + + def OnRemSel(self, row): + layer = manager.layers[row] + manager.clear_log() + count, msg = layer.remove_selection() + if count == 0: + dlg = LogDialog(self, "Remove Selection Log", manager.get_log_text()) + dlg.ShowModal() + dlg.Destroy() + else: + wx.MessageBox(msg) + self.RefreshList() + + def OnInspect(self, row): + layer = manager.layers[row] + wx.MessageBox(layer.inspect(), "Layer Inspection") + + def DoDelete(self, row, delete_items): + manager.delete_layer(row, delete_items) + self.RefreshList() + + def DoClear(self, row): + manager.layers[row].clear_items() + self.RefreshList() + +class LayerWindow(wx.Frame): + def __init__(self): + parent = None + try: + for w in wx.GetTopLevelWindows(): + if "PCB Editor" in w.GetTitle(): + parent = w + break + except: pass + + super().__init__(parent, title="Logical Layers", size=(500, 600), + style=wx.DEFAULT_FRAME_STYLE | wx.FRAME_FLOAT_ON_PARENT) + + self.panel = LayerPanel(self) + self.Bind(wx.EVT_CLOSE, self.OnClose) + self.Bind(wx.EVT_SHOW, self.OnShow) + self.Bind(wx.EVT_ACTIVATE, self.OnActivate) + + def OnShow(self, event): + if event.IsShown(): + manager.load() + self.panel.RefreshList() + event.Skip() + + def OnClose(self, event): + self.Hide() + + def OnActivate(self, event): + if event.GetActive(): + self.SetTransparent(255) # Opaque + else: + self.SetTransparent(180) # ~70% Opaque (30% Transparent) + event.Skip() + +_win = None +def ShowWindow(): + global _win + if not _win: _win = LayerWindow() + _win.Show() + _win.Raise() \ No newline at end of file diff --git a/metadata.json b/metadata.json new file mode 100644 index 0000000..9b6fe9d --- /dev/null +++ b/metadata.json @@ -0,0 +1,11 @@ +{ + "identifier": "com.else-if.logicallayers", + "name": "Logical Layers", + "description": "Photo editor-like logical layers.", + "kicad_version": "7.0", + "version": "0.1", + "status": "development", + "resources": { + "homepage": "https://git.else-if.org/jess/logicallayers" + } +} \ No newline at end of file diff --git a/pcbnew.py.md b/pcbnew.py.md new file mode 100644 index 0000000..dac46f4 --- /dev/null +++ b/pcbnew.py.md @@ -0,0 +1,352 @@ +# Symbol Map: pcbnew.py + +## Classes + +- `class _SwigNonDynamicMeta (Methods: )` +- `class SwigPyIterator (Methods: __init__, value, incr, decr, distance, equal, copy, next, __next__, previous, advance, __eq__, __ne__, __iadd__, __isub__, __add__, __sub__, __iter__)` +- `class string (Methods: length, max_size, capacity, reserve, shrink_to_fit, copy, c_str, find, rfind, find_first_of, find_last_of, find_first_not_of, find_last_not_of, substr, empty, size, swap, begin, end, rbegin, rend, get_allocator, erase, __init__, assign, resize, iterator, __iter__, __nonzero__, __bool__, __len__, __getslice__, __setslice__, __delslice__, __delitem__, __getitem__, __setitem__, insert, replace, __iadd__, __add__, __radd__, __str__, __rlshift__, __eq__, __ne__, __gt__, __lt__, __ge__, __le__)` +- `class KI_PARAM_ERROR (Methods: __init__, What)` +- `class IO_ERROR (Methods: __init__, init, Problem, Where, What)` +- `class wxRect (Methods: __init__, GetX, SetX, GetY, SetY, GetWidth, SetWidth, GetHeight, SetHeight, GetPosition, SetPosition, Get, __eq__, __str__, __repr__, __len__, __getitem__, __setitem__, __nonzero__)` +- `class wxSize (Methods: __init__, Get, SetWidth, SetHeight, GetWidth, GetHeight, Scale, __eq__, __str__, __repr__, __len__, __getitem__, __setitem__, __nonzero__)` +- `class wxPoint (Methods: __init__, __add__, __sub__, Set, Get, __eq__, __ne__, __str__, __repr__, __len__, __getitem__, __setitem__, __nonzero__)` +- `class wxString (Methods: __str__, __repr__, __init__)` +- `class wxPoint_Vector (Methods: iterator, __iter__, __nonzero__, __bool__, __len__, __getslice__, __setslice__, __delslice__, __delitem__, __getitem__, __setitem__, pop, append, empty, size, swap, begin, end, rbegin, rend, clear, get_allocator, pop_back, erase, __init__, push_back, front, back, assign, resize, insert, reserve, capacity)` +- `class KIID (Methods: __init__, Clone, Hash, IsLegacyTimestamp, AsLegacyTimestamp, AsString, AsLegacyTimestampString, AsStdString, SniffTest, CreateNilUuids, SeedGenerator, ConvertTimestampToUuid, Increment, __eq__, __ne__, __lt__, __gt__)` +- `class KIID_VECT_LIST (Methods: iterator, __iter__, __nonzero__, __bool__, __len__, __getslice__, __setslice__, __delslice__, __delitem__, __getitem__, __setitem__, pop, append, empty, size, swap, begin, end, rbegin, rend, clear, get_allocator, pop_back, erase, __init__, push_back, front, back, assign, resize, insert, reserve, capacity)` +- `class KIID_PATH (Methods: __init__, MakeRelativeTo, EndsWith, AsString, __eq__, __lt__, __gt__, __iadd__)` +- `class KIID_NIL_SET_RESET (Methods: __init__)` +- `class EDA_ITEM (Methods: __init__, Type, GetParent, SetParent, IsModified, IsNew, IsMoving, IsSelected, IsEntered, IsBrightened, IsRollover, SetIsRollover, SetSelected, SetBrightened, ClearSelected, ClearBrightened, SetModified, SetFlags, XorFlags, ClearFlags, GetFlags, HasFlag, GetEditFlags, ClearEditFlags, GetTempFlags, ClearTempFlags, RenderAsBitmap, SetIsShownAsBitmap, IsShownAsBitmap, IsType, SetForceVisible, IsForceVisible, GetMsgPanelInfo, GetFriendlyName, HitTest, GetBoundingBox, GetPosition, SetPosition, GetFocusPosition, GetSortPosition, Clone, Visit, GetTypeDesc, GetItemDescription, GetMenuImage, Matches, Replace, IsReplaceable, __lt__, Sort, ViewBBox, ViewGetLayers, GetEmbeddedFiles, PyGetClass, GetClass)` +- `class CompareByUuid (Methods: __call__, __init__)` +- `class EDA_IU_SCALE (Methods: __init__, IUTomm, mmToIU, MilsToIU, IUToMils)` +- `class LINE_READER (Methods: __init__, ReadLine, GetSource, Line, LineNumber, Length)` +- `class FILE_LINE_READER (Methods: __init__, Rewind, FileLength, CurPos)` +- `class STRING_LINE_READER (Methods: __init__)` +- `class INPUTSTREAM_LINE_READER (Methods: __init__)` +- `class OUTPUTFORMATTER (Methods: __init__, Print, GetQuoteChar, Quotes, Quotew, Finish)` +- `class STRING_FORMATTER (Methods: __init__, Clear, StripUseless, GetString)` +- `class FILE_OUTPUTFORMATTER (Methods: __init__)` +- `class PRETTIFIED_FILE_OUTPUTFORMATTER (Methods: __init__)` +- `class TITLE_BLOCK (Methods: __init__, SetTitle, GetTitle, SetDate, GetDate, SetRevision, GetRevision, SetCompany, GetCompany, SetComment, GetComment, Clear, GetContextualTextVars, TextVarResolver, Format, GetCurrentDate)` +- `class StructColors (Methods: __init__)` +- `class COLOR4D (Methods: FromCSSRGBA, __init__, SetFromWxString, ToCSSString, SetFromHexString, ToHexString, ToColour, LegacyMix, ToHSL, FromHSL, Brighten, Darken, Invert, Saturate, Desaturate, Brightened, Darkened, Mix, WithAlpha, Inverted, GetBrightness, ToHSV, FromHSV, Distance, Compare, RelativeLuminance, ContrastRatio, FindNearestLegacyColor)` +- `class MARKER_BASE (Methods: __init__, MarkerScale, SetMarkerScale, ShapeToPolygon, PrintMarker, GetPos, GetUUID, SetMarkerType, GetMarkerType, IsExcluded, SetExcluded, GetComment, GetSeverity, GetRCItem, HitTestMarker, GetBoundingBoxMarker)` +- `class EDA_TEXT (Methods: __init__, Serialize, Deserialize, GetText, GetShownText, HasTextVars, SetText, SetTextThickness, GetTextThickness, GetEffectiveTextPenWidth, SetTextAngle, GetTextAngle, SetTextAngleDegrees, GetTextAngleDegrees, SetItalic, SetItalicFlag, IsItalic, SetBold, SetBoldFlag, IsBold, SetVisible, IsVisible, SetMirrored, IsMirrored, SetMultilineAllowed, IsMultilineAllowed, SetHorizJustify, GetHorizJustify, SetVertJustify, GetVertJustify, SetKeepUpright, IsKeepUpright, FlipHJustify, SwapAttributes, SwapText, CopyText, SetAttributes, GetAttributes, Replace, IsDefaultFormatting, SetFont, GetFont, SetUnresolvedFontName, ResolveFont, GetFontName, SetFontIndex, GetFontIndex, SetLineSpacing, GetLineSpacing, SetTextSize, GetTextSize, SetTextWidth, GetTextWidth, SetTextHeight, GetTextHeight, SetTextColor, GetTextColor, SetTextPos, GetTextPos, SetTextX, SetTextY, Offset, Empty, MapHorizJustify, MapVertJustify, Print, GetEffectiveTextShape, TextHitTest, GetTextBox, GetInterline, GetTextStyleName, GetLinePositions, Levenshtein, Similarity, Format, GetDrawRotation, GetDrawPos, GetDrawFont, ClearRenderCache, ClearBoundingBoxCache, GetRenderCache, SetupRenderCache, AddRenderCacheGlyph, Compare, __eq__, __lt__, __gt__, HasHyperlink, GetHyperlink, SetHyperlink, RemoveHyperlink, ValidateHyperlink, IsGotoPageHref, GotoPageHref)` +- `class GAL_SET (Methods: __init__, set, Contains, Seq, DefaultVisible)` +- `class SETTINGS_MANAGER (Methods: __init__, IsOK, SetKiway, Load, Save, FlushAndRelease, GetColorSettings, GetColorSettingsList, SaveColorSettings, AddNewColorSettings, GetMigratedColorSettings, GetCommonSettings, GetPathForSettingsFile, MigrateIfNeeded, SetMigrationSource, SetMigrateLibraryTables, GetPreviousVersionPaths, ReloadColorSettings, LoadProject, UnloadProject, IsProjectOpen, IsProjectOpenNotDummy, Prj, GetProject, GetOpenProjects, SaveProject, SaveProjectAs, SaveProjectCopy, GetProjectBackupsPath, BackupProject, TriggerBackupIfNeeded, IsSettingsPathValid, GetColorSettingsPath, GetSettingsVersion, GetUserSettingsPath)` +- `class UTILS_BOX3D (Methods: Min, Max, GetCenter, GetSize, __init__)` +- `class UTILS_STEP_MODEL (Methods: GetBoundingBox, Translate, Scale, SaveSTEP, LoadSTEP, __init__)` +- `class intVector (Methods: iterator, __iter__, __nonzero__, __bool__, __len__, __getslice__, __setslice__, __delslice__, __delitem__, __getitem__, __setitem__, pop, append, empty, size, swap, begin, end, rbegin, rend, clear, get_allocator, pop_back, erase, __init__, push_back, front, back, assign, resize, insert, reserve, capacity)` +- `class str_utf8_Map (Methods: iterator, __iter__, __nonzero__, __bool__, __len__, __iter__, iterkeys, itervalues, iteritems, __getitem__, __delitem__, has_key, keys, values, items, __contains__, key_iterator, value_iterator, __setitem__, asdict, __init__, empty, size, swap, begin, end, rbegin, rend, clear, get_allocator, count, erase, find, lower_bound, upper_bound)` +- `class KiCadPlugin (Methods: __init__, register, deregister, GetPluginPath)` +- `class FilePlugin (Methods: __init__)` +- `class FootprintWizardParameter (Methods: __init__, ClearErrors, AddError, Check, value, DefaultValue, SetValue, __str__)` +- `class FootprintWizardPlugin (Methods: __init__, defaults, AddParam, parameters, values, ResetWizard, GetName, GetImage, GetDescription, GetValue, GetReferencePrefix, GetParam, CheckParam, AnyErrors, pages, GetNumParameterPages, GetParameterPageName, GetParametersByPageName, GetParametersByPageIndex, GetParameterDesignators, GetParameterNames, GetParameterValues, GetParameterErrors, GetParameterTypes, GetParameterHints, GetParameterDesignators, SetParameterValues, GetFootprint, BuildFootprint, GetBuildMessages, Show)` +- `class ActionPlugin (Methods: __init__, defaults, GetClassName, GetName, GetCategoryName, GetDescription, GetShowToolbarButton, GetIconFileName, Run)` +- `class VECTOR2I (Methods: __init__, EuclideanNorm, SquaredEuclideanNorm, Perpendicular, Resize, Format, Cross, Dot, Distance, SquaredDistance, __imul__, __iadd__, __isub__, __neg__, __truediv__, __eq__, __ne__, __lt__, __le__, __gt__, __ge__, Set, Get, __eq__, __ne__, __str__, __repr__, __len__, __getitem__, __setitem__, __nonzero__, __add__, __sub__)` +- `class VECTOR2L (Methods: __init__, EuclideanNorm, SquaredEuclideanNorm, Perpendicular, Resize, Format, Cross, Dot, Distance, SquaredDistance, __imul__, __iadd__, __isub__, __neg__, __truediv__, __eq__, __ne__, __lt__, __le__, __gt__, __ge__, Set, Get, __eq__, __ne__, __str__, __repr__, __len__, __getitem__, __setitem__, __nonzero__, __add__, __sub__)` +- `class VECTOR2I_EXTENDED_TYPE (Methods: __init__)` +- `class VECTOR3D (Methods: __init__, Cross, Dot, EuclideanNorm, Normalize, SetAll, __eq__, __ne__, __imul__, __itruediv__, Set, Get, __eq__, __ne__, __str__, __repr__, __len__, __getitem__, __setitem__, __nonzero__)` +- `class BOX2I (Methods: ByCorners, ByCenter, SetMaximum, Centre, Move, Normalize, Contains, GetSize, GetX, GetY, GetOrigin, GetPosition, GetEnd, GetWidth, GetHeight, GetRight, GetBottom, GetLeft, GetTop, GetCenter, GetSizeMax, SetOrigin, SetSize, Offset, GetWithOffset, SetX, SetY, SetWidth, SetHeight, SetEnd, Intersect, Intersects, IntersectsCircle, IntersectsCircleEdge, Format, Inflate, GetInflated, Merge, GetBoundingBoxRotated, GetArea, Diagonal, SquaredDiagonal, SquaredDistance, Distance, NearestPoint, FarthestPointTo, __eq__, __ne__, IsValid, __init__)` +- `class VECTOR_VECTOR2I (Methods: iterator, __iter__, __nonzero__, __bool__, __len__, __getslice__, __setslice__, __delslice__, __delitem__, __getitem__, __setitem__, pop, append, empty, size, swap, begin, end, rbegin, rend, clear, get_allocator, pop_back, erase, __init__, push_back, front, back, assign, resize, insert, reserve, capacity)` +- `class SEG (Methods: __init__, __eq__, __ne__, Square, LineProject, Side, LineDistance, Angle, NearestPoint, NearestPoints, ReflectPoint, Intersect, Intersects, IntersectLines, PerpendicularSeg, ParallelSeg, Collide, SquaredDistance, Distance, CanonicalCoefs, Collinear, ApproxCollinear, ApproxParallel, ApproxPerpendicular, Overlaps, Length, SquaredLength, TCoef, Index, Contains, Reverse, Reversed, Center, __lt__)` +- `class SHAPE_BASE (Methods: __init__, Type, TypeName, HasIndexableSubshapes, GetIndexableSubshapeCount, GetIndexableSubshapes)` +- `class SHAPE (Methods: __init__, Clone, GetClearance, IsNull, Collide, BBox, Centre, Distance, SquaredDistance, PointInside, TransformToPolygon, Rotate, Move, IsSolid, Parse, Format, Cast)` +- `class SHAPE_LINE_CHAIN_BASE (Methods: __init__, Collide, SquaredDistance, PointInside, PointOnEdge, EdgeContainingPoint, GetPoint, GetSegment, GetPointCount, GetSegmentCount, IsClosed, GetCachedBBox)` +- `class SHAPE_ARC (Methods: __init__, ConstructFromStartEndAngle, ConstructFromStartEndCenter, GetP0, GetP1, GetArcMid, GetCenter, BBox, NearestPoint, NearestPoints, Collide, IntersectLine, Intersect, SetWidth, GetWidth, IsEffectiveLine, Mirror, Reverse, Reversed, GetRadius, GetChord, GetCentralAngle, GetStartAngle, GetEndAngle, GetLength, DefaultAccuracyForPCB, ConvertToPolyline, __eq__, IsCCW, IsClockwise)` +- `class SHAPE_CIRCLE (Methods: __init__, BBox, Collide, SetRadius, SetCenter, GetRadius, GetCenter, GetCircle, Rotate, Format)` +- `class SHAPE_COMPOUND (Methods: __init__, Clone, Format, Collide, Shapes, BBox, Distance, AddShape, Empty, Size, Rotate, UniqueSubshape, GetSubshapes)` +- `class CLIPPER_Z_VALUE (Methods: __init__)` +- `class SHAPE_LINE_CHAIN (Methods: __init__, Collide, ClosestPoints, ClosestSegments, ClosestSegmentsFast, Clear, SetClosed, SetWidth, Width, SegmentCount, ShapeCount, RemoveDuplicatePoints, Simplify, Simplify2, PointCount, Segment, CSegment, NextShape, SetPoint, CPoint, CPoints, CLastPoint, CArcs, CShapes, BBox, GenerateBBoxCache, Reverse, ClearArcs, Length, ReservePoints, Append, Insert, Replace, Remove, RemoveShape, Find, FindSegment, Slice, Intersects, Intersect, PathLength, CheckClearance, SelfIntersecting, SelfIntersectingWithArcs, NearestSegment, NearestPoint, Format, __ne__, CompareGeometry, Mirror, Rotate, PointAlong, Area, Split, OffsetLine, ArcCount, ArcIndex, Arc, IsSharedPt, IsPtOnArc, IsArcSegment, IsArcStart, IsArcEnd, Distance)` +- `class SHAPE_POLY_SET (Methods: __init__, CacheTriangulation, IsTriangulationUpToDate, GetHash, GetRelativeIndices, GetGlobalIndex, CloneDropTriangulation, NewOutline, NewHole, AddOutline, AddHole, AddPolygon, Area, ArcCount, GetArcs, ClearArcs, Append, InsertVertex, CVertex, GetNeighbourIndexes, IsPolygonSelfIntersecting, IsSelfIntersecting, TriangulatedPolyCount, OutlineCount, VertexCount, FullPointCount, HoleCount, Outline, Subset, UnitSet, Hole, Polygon, TriangulatedPolygon, COutline, CHole, CPolygon, CPolygons, Iterate, IterateWithHoles, CIterate, CIterateWithHoles, IterateFromVertexWithHoles, IterateSegments, CIterateSegments, IterateSegmentsWithHoles, CIterateSegmentsWithHoles, BooleanAdd, BooleanSubtract, BooleanIntersection, BooleanXor, RebuildHolesFromContours, Inflate, Deflate, OffsetLineChain, InflateWithLinkedHoles, Fracture, Unfracture, HasHoles, HasTouchingHoles, Simplify, SimplifyOutlines, NormalizeAreaOutlines, Format, Mirror, Rotate, BBox, PointOnEdge, Collide, CollideVertex, CollideEdge, PointInside, BuildBBoxCaches, BBoxFromCaches, Contains, IsEmpty, RemoveVertex, RemoveAllContours, RemoveContour, RemoveOutline, RemoveNullSegments, SetVertex, TotalVertices, DeletePolygon, DeletePolygonAndTriangulationData, UpdateTriangulationDataHash, ChamferPolygon, FilletPolygon, Chamfer, Fillet, SquaredDistanceToPolygon, SquaredDistance, SquaredDistanceToSeg, IsVertexInHole, BuildPolysetFromOrientedPaths)` +- `class SHAPE_RECT (Methods: __init__, BBox, GetInflated, Diagonal, MajorDimension, MinorDimension, Collide, GetPosition, GetSize, GetWidth, GetHeight, Rotate, Outline, Format)` +- `class SHAPE_SEGMENT (Methods: __init__, BBox, Collide, SetSeg, GetSeg, SetWidth, GetWidth, Rotate, Is45Degree, Format)` +- `class SHAPE_SIMPLE (Methods: __init__, Clear, BBox, PointCount, CPoint, CDPoint, Vertices, Append, Collide, Rotate)` +- `class VECTOR_SHAPEPTR (Methods: iterator, __iter__, __nonzero__, __bool__, __len__, __getslice__, __setslice__, __delslice__, __delitem__, __getitem__, __setitem__, pop, append, empty, size, swap, begin, end, rbegin, rend, clear, get_allocator, pop_back, erase, __init__, push_back, front, back, assign, resize, insert, reserve, capacity, __iter__)` +- `class UTF8 (Methods: __init__, c_str, empty, find, clear, length, size, compare, __eq__, __ne__, __lt__, __gt__, find_first_of, __iadd__, substr, utf8_to_string, wx_str, utf8_to_wxstring, begin, end, Cast_to_CChar, GetChars, __str__)` +- `class LIB_ID (Methods: __init__, Parse, GetLibNickname, GetUniStringLibNickname, SetLibNickname, GetLibItemName, GetUniStringLibItemName, SetLibItemName, GetSubLibraryName, SetSubLibraryName, GetUniStringSubLibraryName, GetFullLibraryName, GetUniStringLibId, Format, IsValid, IsLegacy, clear, empty, compare, __lt__, __gt__, __eq__, __ne__, HasIllegalChars, FixIllegalChars, FindIllegalLibraryNameChar)` +- `class BASE_SET (Methods: __init__)` +- `class PCB_IO_MGR (Methods: PluginFind, ShowType, EnumFromStr, FindPluginTypeFromBoardPath, GuessPluginTypeFromLibPath, Load, Save, ConvertLibrary, __init__)` +- `class PCB_IO (Methods: __init__, GetBoardFileDesc, CanReadBoard, CanReadFootprint, SetQueryUserCallback, LoadBoard, GetImportedCachedLibraryFootprints, SaveBoard, FootprintEnumerate, GetLibraryTimestamp, ImportFootprint, FootprintLoad, GetEnumeratedFootprint, FootprintExists, FootprintSave, FootprintDelete, GetLibraryOptions, footprintPyEnumerate, FootprintEnumerate, FootprintLibCreate, FootprintLibDelete, IsFootprintLibWritable)` +- `class FP_CACHE_ENTRY (Methods: __init__, GetFileName, SetFilePath, GetFootprint)` +- `class FP_CACHE (Methods: __init__, GetPath, IsWritable, Exists, GetFootprints, Save, Load, Remove, GetTimestamp, IsModified, IsPath, SetPath)` +- `class PCB_IO_KICAD_SEXPR (Methods: GetLibraryFileDesc, GetLibraryDesc, SaveBoard, LoadBoard, DoLoad, FootprintEnumerate, GetEnumeratedFootprint, FootprintExists, ImportFootprint, FootprintLoad, FootprintSave, FootprintDelete, CreateLibrary, DeleteLibrary, IsLibraryWritable, __init__, Format, GetStringOutput, SetOutputFormatter, Parse)` +- `class PLOT_CONTROLLER (Methods: __init__, GetPlotOptions, SetLayer, GetLayer, IsPlotOpen, ClosePlot, OpenPlotfile, PlotLayer, PlotLayers, GetPlotFileName, GetPlotDirName, SetColorMode, GetColorMode, GetPlotter)` +- `class PCB_PLOT_PARAMS (Methods: __init__, SetSkipPlotNPTH_Pads, GetSkipPlotNPTH_Pads, Format, Parse, IsSameAs, SetColorSettings, ColorSettings, SetTextMode, GetTextMode, SetPlotMode, GetPlotMode, SetPlotPadNumbers, GetPlotPadNumbers, SetDXFPlotPolygonMode, GetDXFPlotPolygonMode, SetDXFPlotUnits, GetDXFPlotUnits, SetDrillMarksType, GetDrillMarksType, SetScale, GetScale, SetFineScaleAdjustX, GetFineScaleAdjustX, SetFineScaleAdjustY, GetFineScaleAdjustY, SetWidthAdjust, GetWidthAdjust, SetAutoScale, GetAutoScale, SetMirror, GetMirror, SetSketchPadsOnFabLayers, GetSketchPadsOnFabLayers, SetSketchPadLineWidth, GetSketchPadLineWidth, SetHideDNPFPsOnFabLayers, GetHideDNPFPsOnFabLayers, SetSketchDNPFPsOnFabLayers, GetSketchDNPFPsOnFabLayers, SetCrossoutDNPFPsOnFabLayers, GetCrossoutDNPFPsOnFabLayers, SetPlotValue, GetPlotValue, SetPlotReference, GetPlotReference, SetPlotFPText, GetPlotFPText, SetNegative, GetNegative, GetLegacyPlotViaOnMaskLayer, SetPlotFrameRef, GetPlotFrameRef, SetFormat, GetFormat, SetOutputDirectory, GetOutputDirectory, SetDisableGerberMacros, GetDisableGerberMacros, SetUseGerberX2format, GetUseGerberX2format, SetIncludeGerberNetlistInfo, GetIncludeGerberNetlistInfo, SetCreateGerberJobFile, GetCreateGerberJobFile, SetUseGerberProtelExtensions, GetUseGerberProtelExtensions, SetGerberPrecision, GetGerberPrecision, SetSvgPrecision, GetSvgPrecision, SetSvgFitPageToBoard, GetSvgFitPagetoBoard, SetBlackAndWhite, GetBlackAndWhite, SetSubtractMaskFromSilk, GetSubtractMaskFromSilk, SetLayerSelection, GetLayerSelection, SetPlotOnAllLayersSequence, GetPlotOnAllLayersSequence, SetUseAuxOrigin, GetUseAuxOrigin, SetScaleSelection, GetScaleSelection, SetA4Output, GetA4Output, GetHPGLPenDiameter, SetHPGLPenDiameter, GetHPGLPenSpeed, SetHPGLPenSpeed, SetHPGLPenNum, GetHPGLPenNum, SetDashedLineDashRatio, GetDashedLineDashRatio, SetDashedLineGapRatio, GetDashedLineGapRatio, SetUseGerberAttributes)` +- `class PLOTTER (Methods: __init__, GetPlotterType, StartPlot, EndPlot, SetNegative, SetColorMode, GetColorMode, SetRenderSettings, RenderSettings, SetPageSettings, PageSettings, SetPlotMirrored, GetPlotMirrored, SetCurrentLineWidth, GetCurrentLineWidth, SetColor, SetDash, SetCreator, SetTitle, SetAuthor, SetSubject, AddLineToHeader, ClearHeaderLinesList, SetViewport, OpenFile, GetIUsPerDecimil, GetPlotterArcLowDef, GetPlotterArcHighDef, Rect, Circle, Arc, BezierCurve, PenTo, MoveTo, LineTo, FinishTo, PenFinish, PlotPoly, PlotImage, ThickSegment, ThickArc, ThickRect, ThickCircle, FilledCircle, FlashPadCircle, FlashPadOval, FlashPadRect, FlashPadRoundRect, FlashPadCustom, FlashPadTrapez, FlashRegularPolygon, Text, PlotText, HyperlinkBox, HyperlinkMenu, Bookmark, Marker, SetLayerPolarity, SetTextMode, SetGerberCoordinatesFormat, SetSvgCoordinatesFormat, StartBlock, EndBlock, GetPlotOffsetUserUnits)` +- `class D356_RECORD (Methods: __init__)` +- `class IPC356D_WRITER (Methods: __init__, Write)` +- `class PLACE_FILE_EXPORTER (Methods: __init__, GenPositionData, GenReportData, GetFootprintCount, GetFrontSideName, GetBackSideName, DecorateFilename)` +- `class EXPORTER_VRML (Methods: __init__, ExportVRML_File)` +- `class DRILL_TOOL (Methods: __init__)` +- `class HOLE_INFO (Methods: __init__)` +- `class DRILL_PRECISION (Methods: __init__, GetPrecisionString)` +- `class GENDRILL_WRITER_BASE (Methods: __init__, SetMergeOption, GetOffset, SetPageInfo, SetMapFileFormat, CreateMapFilesSet, GenDrillReportFile, GetDrillFileExt)` +- `class EXCELLON_WRITER (Methods: __init__, GetOffset, SetRouteModeForOvalHoles, SetFormat, SetOptions, CreateDrillandMapFilesSet)` +- `class GERBER_WRITER (Methods: __init__, SetFormat, SetOptions, CreateDrillandMapFilesSet)` +- `class JOBFILE_PARAMS (Methods: __init__)` +- `class GERBER_JOBFILE_WRITER (Methods: __init__, AddGbrFile, CreateJobFile, WriteJSONJobFile)` +- `class base_seqVect (Methods: iterator, __iter__, __nonzero__, __bool__, __len__, __getslice__, __setslice__, __delslice__, __delitem__, __getitem__, __setitem__, pop, append, empty, size, swap, begin, end, rbegin, rend, clear, get_allocator, pop_back, erase, __init__, push_back, front, back, assign, resize, insert, reserve, capacity)` +- `class LSEQ (Methods: __init__, TestLayers)` +- `class LSET (Methods: __init__, Contains, Name, NameToLayer, IsBetween, InternalCuMask, FrontAssembly, BackAssembly, AllCuMask, ExternalCuMask, AllNonCuMask, AllLayersMask, FrontTechMask, FrontBoardTechMask, BackTechMask, BackBoardTechMask, AllTechMask, AllBoardTechMask, FrontMask, BackMask, SideSpecificMask, UserMask, PhysicalLayersMask, UserDefinedLayersMask, ForbiddenFootprintLayers, CuStack, TechAndUserUIOrder, UIOrder, Seq, SeqStackupTop2Bottom, SeqStackupForPlotting, RunOnLayers, ExtractLayer, FlipStandardLayers, LayerCount, ClearCopperLayers, ClearNonCopperLayers, ClearUserDefinedLayers, addLayer, removeLayer, addLayerSet, removeLayerSet, FmtHex, FmtBin, ParseHex, AddLayer, AddLayerSet, RemoveLayer, RemoveLayerSet)` +- `class BOARD_ITEM (Methods: __init__, CopyFrom, SetParentGroup, GetParentGroup, GetX, GetY, GetCenter, SetX, SetY, IsConnected, Similarity, __eq__, IsOnCopperLayer, HasHole, HasDrilledHole, IsTented, GetEffectiveShape, GetEffectiveHoleShape, RunOnChildren, RunOnDescendants, GetParent, GetParentFootprint, GetFPRelativePosition, SetFPRelativePosition, HasLineStroke, GetStroke, SetStroke, GetFontMetrics, GetLayer, BoardLayerCount, BoardCopperLayerCount, BoardLayerSet, GetLayerSet, SetLayerSet, IsSideSpecific, SetLayer, Duplicate, SwapItemData, IsOnLayer, IsKnockout, SetIsKnockout, IsLocked, SetLocked, StyleFromSettings, DeleteStructure, Move, Rotate, Flip, Mirror, Normalize, NormalizeForCompare, GetBoard, GetParentAsString, GetLayerName, TransformShapeToPolygon, Cast, Duplicate, SetPos, SetStartEnd)` +- `class DELETED_BOARD_ITEM (Methods: __init__, GetClass, GetInstance, __eq__)` +- `class UNITS_PROVIDER (Methods: __init__, GetUserUnits, SetUserUnits, GetUnitPair, GetIuScale, GetOriginTransforms, StringFromOptionalValue, StringFromValue, MessageTextFromValue, MessageTextFromMinOptMax, ValueFromString, OptionalValueFromString, AngleValueFromString)` +- `class BOARD_ITEM_CONTAINER (Methods: __init__, AddNative, RemoveNative, DeleteNative, Add, Remove, Delete)` +- `class BOARD_CONNECTED_ITEM (Methods: __init__, ClassOf, GetNet, SetNet, UnpackNet, PackNet, GetNetCode, SetNetCode, GetNetname, GetNetnameMsg, GetShortNetname, GetDisplayNetname, GetOwnClearance, GetClearanceOverrides, GetLocalClearance, GetEffectiveNetClass, GetNetClassName, SetLocalRatsnestVisible, GetLocalRatsnestVisible, GetTeardropParams, SetTeardropsEnabled, GetTeardropsEnabled, SetTeardropBestLengthRatio, GetTeardropBestLengthRatio, SetTeardropMaxLength, GetTeardropMaxLength, SetTeardropBestWidthRatio, GetTeardropBestWidthRatio, SetTeardropMaxWidth, GetTeardropMaxWidth, SetTeardropCurved, GetTeardropCurved, SetTeardropPreferZoneConnections, GetTeardropPreferZoneConnections, SetTeardropAllowSpanTwoTracks, GetTeardropAllowSpanTwoTracks, SetTeardropMaxTrackWidth, GetTeardropMaxTrackWidth)` +- `class netclasses_map (Methods: iterator, __iter__, __nonzero__, __bool__, __len__, __iter__, iterkeys, itervalues, iteritems, __getitem__, __delitem__, has_key, keys, values, items, __contains__, key_iterator, value_iterator, __setitem__, asdict, __init__, empty, size, swap, begin, end, rbegin, rend, clear, get_allocator, count, erase, find, lower_bound, upper_bound)` +- `class VIA_DIMENSION (Methods: __init__, __eq__, __ne__, __lt__)` +- `class DIFF_PAIR_DIMENSION (Methods: __init__, __eq__, __ne__, __lt__)` +- `class TEXT_ITEM_INFO (Methods: __init__, __eq__)` +- `class BOARD_DESIGN_SETTINGS (Methods: __eq__, __ne__, __init__, LoadFromFile, GetStackupDescriptor, GetTeadropParamsList, GetSeverity, Ignore, GetDefaultZoneSettings, SetDefaultZoneSettings, GetCurrentNetClassName, UseNetClassTrack, UseNetClassVia, UseNetClassDiffPair, GetBiggestClearanceValue, GetSmallestClearanceValue, GetTrackWidthIndex, SetTrackWidthIndex, GetCurrentTrackWidth, SetCustomTrackWidth, GetCustomTrackWidth, GetViaSizeIndex, SetViaSizeIndex, GetCurrentViaSize, SetCustomViaSize, GetCustomViaSize, GetCurrentViaDrill, SetCustomViaDrill, GetCustomViaDrill, UseCustomTrackViaSize, GetDiffPairIndex, SetDiffPairIndex, SetCustomDiffPairWidth, GetCustomDiffPairWidth, SetCustomDiffPairGap, GetCustomDiffPairGap, SetCustomDiffPairViaGap, GetCustomDiffPairViaGap, UseCustomDiffPairDimensions, GetCurrentDiffPairWidth, GetCurrentDiffPairGap, GetCurrentDiffPairViaGap, GetEnabledLayers, SetEnabledLayers, IsLayerEnabled, GetCopperLayerCount, SetCopperLayerCount, GetUserDefinedLayerCount, SetUserDefinedLayerCount, GetBoardThickness, SetBoardThickness, GetDRCEpsilon, GetHolePlatingThickness, GetLineThickness, GetTextSize, GetTextThickness, GetTextItalic, GetTextUpright, GetLayerClass, SetAuxOrigin, GetAuxOrigin, SetGridOrigin, GetGridOrigin, SetDefaultMasterPad, CloneFrom)` +- `class NET_SETTINGS (Methods: __init__, __eq__, __ne__, SetDefaultNetclass, GetDefaultNetclass, HasNetclass, SetNetclass, SetNetclasses, GetNetclasses, GetCompositeNetclasses, ClearNetclasses, GetNetclassLabelAssignments, ClearNetclassLabelAssignments, ClearNetclassLabelAssignment, SetNetclassLabelAssignment, AppendNetclassLabelAssignment, HasNetclassLabelAssignment, SetNetclassPatternAssignment, SetNetclassPatternAssignments, GetNetclassPatternAssignments, ClearNetclassPatternAssignments, ClearCacheForNet, ClearAllCaches, SetNetColorAssignment, GetNetColorAssignments, ClearNetColorAssignments, HasEffectiveNetClass, GetCachedEffectiveNetClass, GetEffectiveNetClass, RecomputeEffectiveNetclasses, GetNetClassByName, ParseBusVector, ParseBusGroup)` +- `class CN_DISJOINT_NET_ENTRY (Methods: __init__)` +- `class RN_DYNAMIC_LINE (Methods: __init__)` +- `class CONNECTIVITY_DATA (Methods: __init__, Build, Add, Remove, Update, Move, ClearRatsnest, GetNetCount, GetRatsnestForNet, PropagateNets, FillIsolatedIslandsMap, RecalculateRatsnest, GetUnconnectedCount, IsConnectedOnLayer, GetNodeCount, GetPadCount, GetConnectedTracks, GetConnectedPads, GetConnectedPadsAndVias, GetConnectedItemsAtAnchor, RunOnUnconnectedEdges, TestTrackEndpointDangling, ClearLocalRatsnest, HideLocalRatsnest, ComputeLocalRatsnest, GetLocalRatsnest, GetConnectedItems, GetNetItems, BlockRatsnestItems, GetConnectivityAlgo, GetLock, MarkItemNetAsDirty, RemoveInvalidRefs, SetProgressReporter, GetNetSettings, HasNetNameForNetCode, GetNetNameForNetCode, RefreshNetcodeMap, GetFromToCache)` +- `class MARKERS (Methods: iterator, __iter__, __nonzero__, __bool__, __len__, __getslice__, __setslice__, __delslice__, __delitem__, __getitem__, __setitem__, pop, append, empty, size, swap, begin, end, rbegin, rend, clear, get_allocator, pop_back, erase, __init__, push_back, front, back, assign, resize, insert, reserve, capacity)` +- `class ZONES (Methods: iterator, __iter__, __nonzero__, __bool__, __len__, __getslice__, __setslice__, __delslice__, __delitem__, __getitem__, __setitem__, pop, append, empty, size, swap, begin, end, rbegin, rend, clear, get_allocator, pop_back, erase, __init__, push_back, front, back, assign, resize, insert, reserve, capacity)` +- `class TRACKS (Methods: iterator, __iter__, __nonzero__, __bool__, __len__, __getslice__, __setslice__, __delslice__, __delitem__, __getitem__, __setitem__, pop, append, empty, size, swap, begin, end, rbegin, rend, clear, get_allocator, pop_back, erase, __init__, push_back, front, back, assign, resize, insert, pop_front, push_front, __iter__)` +- `class FOOTPRINTS (Methods: iterator, __iter__, __nonzero__, __bool__, __len__, __getslice__, __setslice__, __delslice__, __delitem__, __getitem__, __setitem__, pop, append, empty, size, swap, begin, end, rbegin, rend, clear, get_allocator, pop_back, erase, __init__, push_back, front, back, assign, resize, insert, pop_front, push_front)` +- `class GROUPS (Methods: iterator, __iter__, __nonzero__, __bool__, __len__, __getslice__, __setslice__, __delslice__, __delitem__, __getitem__, __setitem__, pop, append, empty, size, swap, begin, end, rbegin, rend, clear, get_allocator, pop_back, erase, __init__, push_back, front, back, assign, resize, insert, pop_front, push_front)` +- `class GENERATORS (Methods: iterator, __iter__, __nonzero__, __bool__, __len__, __getslice__, __setslice__, __delslice__, __delitem__, __getitem__, __setitem__, pop, append, empty, size, swap, begin, end, rbegin, rend, clear, get_allocator, pop_back, erase, __init__, push_back, front, back, assign, resize, insert, pop_front, push_front)` +- `class DRAWINGS (Methods: iterator, __iter__, __nonzero__, __bool__, __len__, __getslice__, __setslice__, __delslice__, __delitem__, __getitem__, __setitem__, pop, append, empty, size, swap, begin, end, rbegin, rend, clear, get_allocator, pop_back, erase, __init__, push_back, front, back, assign, resize, insert, pop_front, push_front, __iter__)` +- `class PADS (Methods: iterator, __iter__, __nonzero__, __bool__, __len__, __getslice__, __setslice__, __delslice__, __delitem__, __getitem__, __setitem__, pop, append, empty, size, swap, begin, end, rbegin, rend, clear, get_allocator, pop_back, erase, __init__, push_back, front, back, assign, resize, insert, pop_front, push_front)` +- `class PCB_FIELDS (Methods: iterator, __iter__, __nonzero__, __bool__, __len__, __getslice__, __setslice__, __delslice__, __delitem__, __getitem__, __setitem__, pop, append, empty, size, swap, begin, end, rbegin, rend, clear, get_allocator, pop_back, erase, __init__, push_back, front, back, assign, resize, insert, pop_front, push_front)` +- `class PCB_FIELD_VEC (Methods: iterator, __iter__, __nonzero__, __bool__, __len__, __getslice__, __setslice__, __delslice__, __delitem__, __getitem__, __setitem__, pop, append, empty, size, swap, begin, end, rbegin, rend, clear, get_allocator, pop_back, erase, __init__, push_back, front, back, assign, resize, insert, reserve, capacity)` +- `class PADSTACK (Methods: __init__, __eq__, __ne__, Serialize, Deserialize, Compare, Similarity, LayerSet, SetLayerSet, FlipLayers, StartLayer, EndLayer, Mode, SetMode, Name, GetOrientation, SetOrientation, Drill, SecondaryDrill, UnconnectedLayerMode, SetUnconnectedLayerMode, CopperLayer, FrontOuterLayers, BackOuterLayers, IsTented, CustomShapeInZoneMode, SetCustomShapeInZoneMode, ForEachUniqueLayer, UniqueLayers, EffectiveLayerFor, RelevantShapeLayers, Shape, SetShape, SetSize, Size, DrillShape, SetDrillShape, Offset, AnchorShape, SetAnchorShape, TrapezoidDeltaSize, RoundRectRadiusRatio, SetRoundRectRadiusRatio, RoundRectRadius, SetRoundRectRadius, ChamferRatio, SetChamferRatio, ChamferPositions, SetChamferPositions, Clearance, SolderMaskMargin, SolderPasteMargin, SolderPasteMarginRatio, ZoneConnection, ThermalSpokeWidth, ThermalGap, DefaultThermalSpokeAngleForShape, ThermalSpokeAngle, SetThermalSpokeAngle, Primitives, AddPrimitive, AppendPrimitives, ReplacePrimitives, ClearPrimitives)` +- `class PAD (Methods: __init__, Serialize, Deserialize, PTHMask, SMDMask, ConnSMDMask, UnplatedHoleMask, ApertureMask, ClassOf, ImportSettingsFrom, IsFlipped, SetNumber, GetNumber, CanHaveNumber, SetPinFunction, GetPinFunction, SetPinType, GetPinType, SameLogicalPadAs, SharesNetTieGroup, IsNoConnectPad, IsFreePad, SetFrontShape, GetFrontShape, GetAnchorPadShape, GetCustomShapeInZoneOpt, SetCustomShapeInZoneOpt, SetAnchorPadShape, SetY, SetX, SetSizeX, GetSizeX, SetSizeY, GetSizeY, SetDrillSize, GetDrillSize, SetDrillSizeX, GetDrillSizeX, SetDrillSizeY, GetDrillSizeY, Padstack, SetPadstack, AddPrimitivePoly, MergePrimitivesAsPolygon, DeletePrimitivesList, GetPrimitives, FlipPrimitives, ReplacePrimitives, AppendPrimitives, AddPrimitiveShape, SetOrientation, SetFPRelativeOrientation, GetOrientation, GetFPRelativeOrientation, SetOrientationDegrees, GetOrientationDegrees, SetDrillShape, GetDrillShape, IsDirty, SetDirty, SetAttribute, GetAttribute, SetProperty, GetProperty, IsAperturePad, SetPadToDieLength, GetPadToDieLength, SetLocalClearance, GetLocalSolderMaskMargin, SetLocalSolderMaskMargin, GetLocalSolderPasteMargin, SetLocalSolderPasteMargin, GetLocalSolderPasteMarginRatio, SetLocalSolderPasteMarginRatio, SetLocalZoneConnection, GetLocalZoneConnection, GetOwnClearance, TransformShapeToPolygon, TransformHoleToPolygon, GetEffectiveShape, GetEffectivePolygon, GetBoundingRadius, GetLocalClearance, GetSolderMaskExpansion, GetSolderPasteMargin, GetZoneConnectionOverrides, SetLocalThermalSpokeWidthOverride, GetLocalThermalSpokeWidthOverride, GetLocalSpokeWidthOverride, SetThermalSpokeAngle, GetThermalSpokeAngle, SetThermalSpokeAngleDegrees, GetThermalSpokeAngleDegrees, SetThermalGap, GetThermalGap, GetLocalThermalGapOverride, SetLocalThermalGapOverride, ShapePos, SetFrontRoundRectRadiusRatio, GetFrontRoundRectRadiusRatio, SetFrontRoundRectRadiusSize, GetFrontRoundRectRadiusSize, GetSubRatsnest, SetSubRatsnest, SetRemoveUnconnected, GetRemoveUnconnected, SetKeepTopBottom, GetKeepTopBottom, SetUnconnectedLayerMode, GetUnconnectedLayerMode, ConditionallyFlashed, CanFlashLayer, GetPrincipalLayer, FlashLayer, HitTest, Recombine, GetClass, GetBoundingBox, Compare, ShowPadShape, ShowPadAttr, ClonePad, BuildEffectiveShapes, BuildEffectivePolygon, ViewGetLOD, ClearZoneLayerOverrides, GetZoneLayerOverride, SetZoneLayerOverride, CheckPad, __eq__, GetShape, SetShape, GetSize, SetSize, GetDelta, SetDelta, GetOffset, SetOffset, GetRoundRectCornerRadius, SetRoundRectCornerRadius, GetRoundRectRadiusRatio, SetRoundRectRadiusRatio, GetChamferRectRatio, SetChamferRectRatio, GetChamferPositions, SetChamferPositions, SetPadName, SetName, GetPadName, GetName, AddPrimitive, GetCustomShapeAsPolygon)` +- `class PCB_TRACK (Methods: ClassOf, __init__, SetWidth, GetWidth, SetEnd, GetEnd, SetStart, GetStart, SetStartX, SetStartY, GetStartX, GetStartY, SetEndX, SetEndY, GetEndX, GetEndY, GetEndPoint, SetHasSolderMask, HasSolderMask, SetLocalSolderMaskMargin, GetLocalSolderMaskMargin, GetSolderMaskExpansion, GetLength, TransformShapeToPolygon, GetEffectiveShape, IsPointOnEnds, IsNull, HitTest, ApproxCollinear, GetClass, GetWidthConstraint, ViewGetLOD, __eq__, Serialize, Deserialize)` +- `class PCB_ARC (Methods: __init__, ClassOf, SetMid, GetMid, GetRadius, GetAngle, GetArcAngleStart, GetArcAngleEnd, HitTest, IsCCW, GetClass, GetEffectiveShape, IsDegenerated, __eq__, Serialize, Deserialize)` +- `class PCB_VIA (Methods: ClassOf, __init__, HasValidLayerPair, GetViaType, SetViaType, Padstack, SetPadstack, SetWidth, GetWidth, SetFrontWidth, GetFrontWidth, GetWidthConstraint, GetDrillConstraint, SetFrontTentingMode, GetFrontTentingMode, SetBackTentingMode, GetBackTentingMode, GetSolderMaskExpansion, SetLayerPair, SetBottomLayer, SetTopLayer, LayerPair, TopLayer, BottomLayer, SanitizeLayers, HitTest, GetClass, ViewGetLOD, GetMinAnnulus, SetRemoveUnconnected, GetRemoveUnconnected, SetKeepStartEnd, GetKeepStartEnd, ConditionallyFlashed, FlashLayer, GetOutermostConnectedLayers, SetDrill, GetDrill, GetDrillValue, SetDrillDefault, GetIsFree, SetIsFree, GetEffectiveShape, ClearZoneLayerOverrides, GetZoneLayerOverride, SetZoneLayerOverride, __eq__, Serialize, Deserialize)` +- `class ISOLATED_ISLANDS (Methods: __init__)` +- `class ZONE (Methods: __init__, ClassOf, Serialize, Deserialize, InitDataFromSrcInCopyCtor, IsConflicting, SetAssignedPriority, GetAssignedPriority, HigherPriority, SameNet, SetLayerSetAndRemoveUnusedFills, GetZoneName, SetZoneName, CacheBoundingBox, SetLocalClearance, GetLocalClearance, GetFirstLayer, ViewGetLOD, SetFillMode, GetFillMode, SetThermalReliefGap, GetThermalReliefGap, SetThermalReliefSpokeWidth, GetThermalReliefSpokeWidth, CalculateFilledArea, CalculateOutlineArea, GetFilledArea, GetOutlineArea, GetLock, GetFillFlag, SetFillFlag, IsFilled, SetIsFilled, NeedRefill, SetNeedRefill, GetPadConnection, SetPadConnection, GetMinThickness, SetMinThickness, GetHatchThickness, SetHatchThickness, GetHatchGap, SetHatchGap, GetHatchOrientation, SetHatchOrientation, GetHatchSmoothingLevel, SetHatchSmoothingLevel, GetHatchSmoothingValue, SetHatchSmoothingValue, GetHatchHoleMinArea, SetHatchHoleMinArea, GetHatchBorderAlgorithm, SetHatchBorderAlgorithm, GetSelectedCorner, SetSelectedCorner, GetLocalFlags, SetLocalFlags, Outline, SetOutline, GetEffectiveShape, HitTestFilledArea, HitTestCutout, GetInteractingZones, TransformSolidAreasShapesToPolygon, TransformSmoothedOutlineToPolygon, TransformShapeToPolygon, HitTestForCorner, HitTestForEdge, HitTest, UnFill, MoveEdge, GetClass, GetNumCorners, Iterate, IterateWithHoles, CIterateWithHoles, RemoveAllContours, GetCornerPosition, SetCornerPosition, NewHole, AppendCorner, GetHatchStyle, SetHatchStyle, HasFilledPolysForLayer, GetFilledPolysList, GetFill, CacheTriangulation, SetFilledPolysList, IsIsland, SetIsIsland, BuildSmoothedPoly, SetCornerSmoothingType, GetCornerSmoothingType, SetCornerRadius, GetCornerRadius, RemoveCutout, AddPolygon, IsTeardropArea, SetTeardropAreaType, GetTeardropAreaType, HasKeepoutParametersSet, GetIsRuleArea, GetRuleAreaPlacementEnabled, GetRuleAreaPlacementSourceType, GetRuleAreaPlacementSource, GetDoNotAllowCopperPour, GetDoNotAllowVias, GetDoNotAllowTracks, GetDoNotAllowPads, GetDoNotAllowFootprints, SetIsRuleArea, SetRuleAreaPlacementEnabled, SetRuleAreaPlacementSourceType, SetRuleAreaPlacementSource, SetDoNotAllowCopperPour, SetDoNotAllowVias, SetDoNotAllowTracks, SetDoNotAllowPads, SetDoNotAllowFootprints, GetIslandRemovalMode, SetIslandRemovalMode, GetMinIslandArea, SetMinIslandArea, GetBorderHatchPitch, GetDefaultHatchPitch, SetBorderDisplayStyle, SetBorderHatchPitch, UnHatchBorder, HatchBorder, GetHatchLines, BuildHashValue, GetHashValue, __eq__)` +- `class ZONE_FILLER (Methods: SetProgressReporter, GetProgressReporter, Fill, IsDebug, __init__)` +- `class ZONE_SETTINGS (Methods: __init__, __eq__, __ne__, __lshift__, GetDefaultSettings, SetupLayersList, ExportSetting, SetCornerSmoothingType, GetCornerSmoothingType, SetCornerRadius, GetCornerRadius, GetPadConnection, SetPadConnection, HasKeepoutParametersSet, GetIsRuleArea, GetRuleAreaPlacementEnabled, GetRuleAreaPlacementSourceType, GetRuleAreaPlacementSource, GetDoNotAllowCopperPour, GetDoNotAllowVias, GetDoNotAllowTracks, GetDoNotAllowPads, GetDoNotAllowFootprints, SetIsRuleArea, SetRuleAreaPlacementEnabled, SetRuleAreaPlacementSourceType, SetRuleAreaPlacementSource, SetDoNotAllowCopperPour, SetDoNotAllowVias, SetDoNotAllowTracks, SetDoNotAllowPads, SetDoNotAllowFootprints, GetIslandRemovalMode, SetIslandRemovalMode, GetMinIslandArea, SetMinIslandArea)` +- `class EDA_ANGLE (Methods: __init__, AsDegrees, AsTenthsOfADegree, AsRadians, IsCardinal, IsCardinal90, IsZero, IsHorizontal, IsVertical, IsParallelTo, Invert, Sin, Cos, Tan, Arccos, Arcsin, Arctan, Arctan2, Normalize, Normalized, NormalizeNegative, Normalize90, Normalize180, Normalize720, KeepUpright, Round, __iadd__, __isub__, __add__, __sub__, __mul__, __rmul__, __truediv__, __abs__)` +- `class ARC_MID (Methods: __init__)` +- `class EDA_SHAPE (Methods: __init__, SwapShape, Serialize, Deserialize, ShowShape, SHAPE_T_asString, IsProxyItem, SetIsProxyItem, IsFilled, IsFilledForHitTesting, SetFilled, SetFillMode, GetFillMode, IsClosed, GetFillColor, SetFillColor, SetWidth, GetWidth, GetEffectiveWidth, SetLineStyle, GetLineStyle, SetLineColor, GetLineColor, SetShape, GetShape, GetStart, GetStartY, GetStartX, SetStart, SetStartY, SetStartX, SetCenterY, SetCenterX, GetEnd, GetEndY, GetEndX, SetEnd, SetEndY, SetEndX, SetRadius, GetTopLeft, GetBotRight, SetTop, SetLeft, SetRight, SetBottom, SetBezierC1, GetBezierC1, SetBezierC2, GetBezierC2, SetCenter, SetArcAngleAndEnd, GetArcAngle, GetSegmentAngle, EndsSwapped, GetArcMid, GetRectCorners, GetCornersInSequence, CalcArcAngles, GetRadius, SetArcGeometry, SetCachedArcData, GetBezierPoints, DupPolyPointsList, GetPointCount, GetPolyShape, IsPolyShapeValid, SetPolyShape, SetPolyPoints, RebuildBezierToSegmentsPointsList, MakeEffectiveShapes, ShapeGetMsgPanelInfo, SetLength, SetRectangleHeight, SetRectangleWidth, SetRectangle, SetSegmentAngle, IsClockwiseArc, GetLength, GetRectangleHeight, GetRectangleWidth, TransformShapeToPolygon, Compare, Similarity, __eq__)` +- `class PCB_SHAPE (Methods: __init__, ClassOf, GetClass, Serialize, Deserialize, GetConnectionPoints, GetCorners, GetEffectiveShape, SetIsProxyItem, HitTest, Scale, TransformShapeToPolygon, ViewGetLOD, __eq__, SetHasSolderMask, HasSolderMask, SetLocalSolderMaskMargin, GetLocalSolderMaskMargin, GetSolderMaskExpansion, GetArcAngleStart, GetShapeStr)` +- `class PCB_TEXT (Methods: __init__, ClassOf, Serialize, Deserialize, KeepUpright, GetShownText, TextHitTest, HitTest, GetClass, TransformTextToPolySet, TransformShapeToPolygon, GetEffectiveShape, GetKnockoutCache, GetTextTypeDescription, ViewGetLOD, __eq__)` +- `class PCB_TEXTBOX (Methods: __init__, ClassOf, Serialize, Deserialize, GetLegacyTextMargin, SetMarginLeft, SetMarginTop, SetMarginRight, SetMarginBottom, GetMarginLeft, GetMarginTop, GetMarginRight, GetMarginBottom, GetDrawPos, GetShownText, HitTest, GetClass, TransformTextToPolySet, TransformShapeToPolygon, GetEffectiveShape, ViewGetLOD, IsBorderEnabled, SetBorderEnabled, SetBorderWidth, GetBorderWidth, __eq__)` +- `class TEXT_ATTRIBUTES (Methods: __init__, Compare, __eq__, __gt__, __lt__)` +- `class PCB_FIELD (Methods: __init__, Serialize, Deserialize, ClassOf, GetClass, IsReference, IsValue, IsDatasheet, IsComponentClass, IsMandatory, IsHypertext, ViewGetLOD, CloneField, GetName, GetCanonicalName, SetName, GetId, SetId, __eq__)` +- `class PCB_DIMENSION_BASE (Methods: __init__, Serialize, Deserialize, GetStart, SetStart, GetEnd, SetEnd, GetOverrideTextEnabled, SetOverrideTextEnabled, GetOverrideText, SetOverrideText, ChangeOverrideText, GetMeasuredValue, SetMeasuredValue, GetValueText, Update, UpdateUnits, GetPrefix, SetPrefix, ChangePrefix, GetSuffix, SetSuffix, ChangeSuffix, GetArrowDirection, SetArrowDirection, ChangeArrowDirection, GetUnits, SetUnits, GetUnitsMode, SetUnitsMode, ChangeUnitsMode, SetAutoUnits, GetUnitsFormat, SetUnitsFormat, ChangeUnitsFormat, GetPrecision, SetPrecision, ChangePrecision, GetSuppressZeroes, SetSuppressZeroes, ChangeSuppressZeroes, GetKeepTextAligned, SetKeepTextAligned, GetTextAngleDegreesProp, ChangeTextAngleDegrees, ChangeKeepTextAligned, SetTextPositionMode, GetTextPositionMode, GetArrowLength, SetArrowLength, SetExtensionOffset, GetExtensionOffset, GetLineThickness, SetLineThickness, GetShapes, HitTest, GetEffectiveShape, TransformShapeToPolygon, __eq__)` +- `class PCB_DIM_ALIGNED (Methods: __init__, Serialize, Deserialize, ClassOf, GetCrossbarStart, GetCrossbarEnd, SetHeight, GetHeight, ChangeHeight, UpdateHeight, SetExtensionHeight, GetExtensionHeight, ChangeExtensionHeight, GetAngle, GetClass)` +- `class PCB_DIM_ORTHOGONAL (Methods: __init__, Serialize, Deserialize, ClassOf, SetOrientation, GetOrientation, GetClass)` +- `class PCB_DIM_RADIAL (Methods: __init__, Serialize, Deserialize, ClassOf, SetLeaderLength, GetLeaderLength, ChangeLeaderLength, GetKnee, GetClass)` +- `class PCB_DIM_LEADER (Methods: __init__, Serialize, Deserialize, ClassOf, GetClass, SetTextBorder, GetTextBorder, ChangeTextBorder)` +- `class PCB_DIM_CENTER (Methods: __init__, Serialize, Deserialize, ClassOf, GetClass)` +- `class PCB_MARKER (Methods: __init__, ClassOf, SerializeToString, DeserializeFromString, HitTest, GetColorLayer, GetEffectiveShape, SetZoom, GetClass, GetShapes1, GetShapes2, SetShapes1, SetShapes2)` +- `class PCB_TARGET (Methods: __init__, ClassOf, SetShape, GetShape, SetSize, GetSize, SetWidth, GetWidth, GetClass, HitTest, GetEffectiveShape, TransformShapeToPolygon, __eq__)` +- `class PCB_TABLE (Methods: __init__, ClassOf, GetClass, SetStrokeExternal, StrokeExternal, SetStrokeHeaderSeparator, StrokeHeaderSeparator, SetBorderStroke, GetBorderStroke, SetBorderWidth, GetBorderWidth, SetBorderStyle, GetBorderStyle, SetBorderColor, GetBorderColor, SetSeparatorsStroke, GetSeparatorsStroke, SetSeparatorsWidth, GetSeparatorsWidth, SetSeparatorsStyle, GetSeparatorsStyle, SetSeparatorsColor, GetSeparatorsColor, SetStrokeColumns, StrokeColumns, SetStrokeRows, StrokeRows, RunOnDescendants, GetEnd, SetPositionX, SetPositionY, GetPositionX, GetPositionY, SetColCount, GetColCount, GetRowCount, SetColWidth, GetColWidth, SetRowHeight, GetRowHeight, GetCell, GetCells, AddCell, InsertCell, ClearCells, DeleteMarkedCells, AddNative, RemoveNative, DrawBorders, GetEffectiveShape, TransformShapeToPolygon, HitTest, __eq__, Compare, GetHash)` +- `class PADS_VEC (Methods: iterator, __iter__, __nonzero__, __bool__, __len__, __getslice__, __setslice__, __delslice__, __delitem__, __getitem__, __setitem__, pop, append, empty, size, swap, begin, end, rbegin, rend, clear, get_allocator, pop_back, erase, __init__, push_back, front, back, assign, resize, insert, reserve, capacity)` +- `class TRACKS_VEC (Methods: iterator, __iter__, __nonzero__, __bool__, __len__, __getslice__, __setslice__, __delslice__, __delitem__, __getitem__, __setitem__, pop, append, empty, size, swap, begin, end, rbegin, rend, clear, get_allocator, pop_back, erase, __init__, push_back, front, back, assign, resize, insert, reserve, capacity)` +- `class NETINFO_ITEM (Methods: __init__, ClassOf, GetClass, SetNetClass, GetNetClass, GetNetClassSlow, GetNetCode, SetNetCode, GetNetname, GetShortNetname, GetDisplayNetname, HasAutoGeneratedNetname, SetNetname, IsCurrent, SetIsCurrent, Clear, SetParent, GetParent, GetNetClassName)` +- `class NETNAMES_MAP (Methods: iterator, __iter__, __nonzero__, __bool__, __len__, __iter__, iterkeys, itervalues, iteritems, __getitem__, __delitem__, has_key, keys, values, items, __contains__, key_iterator, value_iterator, __setitem__, asdict, __init__, empty, size, swap, begin, end, rbegin, rend, clear, get_allocator, count, erase, find, lower_bound, upper_bound)` +- `class NETCODES_MAP (Methods: iterator, __iter__, __nonzero__, __bool__, __len__, __iter__, iterkeys, itervalues, iteritems, __getitem__, __delitem__, has_key, keys, values, items, __contains__, key_iterator, value_iterator, __setitem__, asdict, __init__, empty, size, swap, begin, end, rbegin, rend, clear, get_allocator, count, erase, find, lower_bound, upper_bound)` +- `class NETINFO_LIST (Methods: __init__, GetNetItem, GetNetCount, NetsByName, NetsByNetcode, RebuildDisplayNetnames, OrphanedItem, GetParent)` +- `class STRINGSET (Methods: iterator, __iter__, __nonzero__, __bool__, __len__, append, __contains__, __getitem__, add, discard, __init__, empty, size, clear, swap, count, begin, end, rbegin, rend, erase, find, lower_bound, upper_bound, equal_range, insert)` +- `class NETCLASS (Methods: __init__, __eq__, GetClass, Serialize, Deserialize, ResetParents, ResetParameters, GetConstituentNetclasses, SetConstituentNetclasses, ContainsNetclassWithName, IsDefault, SetName, GetName, GetHumanReadableName, GetDescription, SetDescription, HasClearance, GetClearance, GetClearanceOpt, SetClearance, SetClearanceParent, GetClearanceParent, HasTrackWidth, GetTrackWidth, GetTrackWidthOpt, SetTrackWidth, SetTrackWidthParent, GetTrackWidthParent, HasViaDiameter, GetViaDiameter, GetViaDiameterOpt, SetViaDiameter, SetViaDiameterParent, GetViaDiameterParent, HasViaDrill, GetViaDrill, GetViaDrillOpt, SetViaDrill, SetViaDrillParent, GetViaDrillParent, HasuViaDiameter, GetuViaDiameter, GetuViaDiameterOpt, SetuViaDiameter, SetuViaDiameterParent, GetuViaDiameterParent, HasuViaDrill, GetuViaDrill, GetuViaDrillOpt, SetuViaDrill, SetuViaDrillParent, GetuViaDrillParent, HasDiffPairWidth, GetDiffPairWidth, GetDiffPairWidthOpt, SetDiffPairWidth, SetDiffPairWidthParent, GetDiffPairWidthParent, HasDiffPairGap, GetDiffPairGap, GetDiffPairGapOpt, SetDiffPairGap, SetDiffPairGapParent, GetDiffPairGapParent, HasDiffPairViaGap, GetDiffPairViaGap, GetDiffPairViaGapOpt, SetDiffPairViaGap, SetDiffPairViaGapParent, GetDiffPairViaGapParent, HasPcbColor, GetPcbColor, SetPcbColor, SetPcbColorParent, GetPcbColorParent, HasWireWidth, GetWireWidth, GetWireWidthOpt, SetWireWidth, SetWireWidthParent, GetWireWidthParent, HasBusWidth, GetBusWidth, GetBusWidthOpt, SetBusWidth, SetBusWidthParent, GetBusWidthParent, GetSchematicColor, SetSchematicColor, SetSchematicColorParent, GetSchematicColorParent, HasLineStyle, GetLineStyle, GetLineStyleOpt, SetLineStyle, SetLineStyleParent, GetLineStyleParent, SetPriority, GetPriority)` +- `class PCB_GROUP (Methods: __init__, ClassOf, GetClass, GetName, SetName, GetItems, AddItem, RemoveItem, RemoveAll, TopLevelGroup, WithinScope, __eq__, DeepClone, DeepDuplicate, HitTest, GetEffectiveShape, ViewGetLOD, RunOnDescendants, IsGroupableType, GetItemsDeque, GetItems)` +- `class PCB_REFERENCE_IMAGE (Methods: __init__, GetReferenceImage, ClassOf, GetClass, ViewGetLOD, GetEffectiveShape, HitTest, __eq__)` +- `class VIA_DIMENSION_Vector (Methods: iterator, __iter__, __nonzero__, __bool__, __len__, __getslice__, __setslice__, __delslice__, __delitem__, __getitem__, __setitem__, pop, append, empty, size, swap, begin, end, rbegin, rend, clear, get_allocator, pop_back, erase, __init__, push_back, front, back, assign, resize, insert, reserve, capacity)` +- `class PTR_PTR_CACHE_KEY (Methods: __eq__, __init__)` +- `class PTR_LAYER_CACHE_KEY (Methods: __eq__, __init__)` +- `class PTR_PTR_LAYER_CACHE_KEY (Methods: __eq__, __init__)` +- `class LAYER (Methods: __init__, clear, ShowType, ParseType)` +- `class HIGH_LIGHT_INFO (Methods: __init__)` +- `class BOARD_LISTENER (Methods: OnBoardItemAdded, OnBoardItemsAdded, OnBoardItemRemoved, OnBoardItemsRemoved, OnBoardNetSettingsChanged, OnBoardItemChanged, OnBoardItemsChanged, OnBoardHighlightNetChanged, OnBoardRatsnestChanged, OnBoardCompositeUpdate, __init__)` +- `class BOARD (Methods: __init__, ClassOf, SetBoardUse, GetBoardUse, IncrementTimeStamp, GetTimeStamp, IsFootprintHolder, SetFileName, GetFileName, Footprints, Zones, Generators, Markers, Drawings, Tracks, GetItemSet, Groups, AllConnectedItems, GetProperties, SetProperties, GetContextualTextVars, ResolveTextVar, IsEmpty, RunOnDescendants, SetFileFormatVersionAtLoad, GetFileFormatVersionAtLoad, SetGenerator, GetGenerator, AddNative, RemoveNative, RemoveAll, HasItemsOnLayer, RemoveAllItemsOnLayer, BulkRemoveStaleTeardrops, FinalizeBulkAdd, FinalizeBulkRemove, FixupEmbeddedData, RunOnNestedEmbeddedFiles, CacheTriangulation, GetFirstFootprint, DeleteAllFootprints, DetachAllFootprints, GetItem, FillItemMap, ConvertCrossReferencesToKIIDs, ConvertKIIDsToCrossReferences, GetConnectivity, BuildConnectivity, DeleteMARKERs, GetProject, SetProject, ClearProject, ResolveDRCExclusions, RecordDRCExclusions, UpdateRatsnestExclusions, ResetNetHighLight, GetHighLightNetCodes, SetHighLightNet, IsHighLightNetON, HighLightON, HighLightOFF, GetCopperLayerCount, SetCopperLayerCount, GetUserDefinedLayerCount, SetUserDefinedLayerCount, GetCopperLayerStackMaxId, FlipLayer, LayerDepth, GetEnabledLayers, SetEnabledLayers, IsLayerEnabled, IsLayerVisible, GetVisibleLayers, SetVisibleLayers, GetVisibleElements, SetVisibleElements, SetVisibleAlls, IsElementVisible, SetElementVisibility, IsFootprintLayerVisible, GetDesignSettings, GetStackupOrDefault, GetPageSettings, SetPageSettings, GetPlotOptions, SetPlotOptions, GetTitleBlock, SetTitleBlock, GetUserUnits, SetUserUnits, UpdateUserUnits, GetBoardPolygonOutlines, GetOutlinesChainingEpsilon, SetOutlinesChainingEpsilon, ConvertBrdLayerToPolygonalContours, GetLayerID, GetLayerName, SetLayerName, GetStandardLayerName, SetLayerDescr, IsFrontLayer, IsBackLayer, GetLayerType, SetLayerType, GetNodesCount, GetPads, BuildListOfNets, FindNet, MatchDpSuffix, DpCoupledNet, GetNetInfo, RemoveUnusedNets, GetNetCount, ComputeBoundingBox, GetBoardEdgesBoundingBox, FindFootprintByReference, FindFootprintByPath, GetNetClassAssignmentCandidates, SynchronizeNetsAndNetClasses, SynchronizeProperties, GetClass, SetAreasNetCodesFromNetNames, GetArea, GetZoneList, GetAreaCount, TestZoneIntersection, GetPad, GetSortedPadListByXthenYCoord, GetTrackLength, TracksInNet, GetFootprint, GetMaxClearanceValue, MapNets, SanitizeNetcodes, AddListener, RemoveListener, RemoveAllListeners, OnItemChanged, OnItemsChanged, OnItemsCompositeUpdate, OnRatsnestChanged, GroupsSanityCheck, GroupsSanityCheckInternal, GroupLegalOps, LegacyTeardrops, SetLegacyTeardrops, GetEmbeddedFiles, SetEmbeddedFilesDelegate, GetFonts, EmbedFonts, GetComponentClassManager, __init__, GetFootprints, GetDrawings, GetTracks, Save, GetNetClasses, GetCurrentNetClassName, GetViasDimensionsList, GetTrackWidthList, GetNetsByName, GetNetsByNetcode, GetNetcodeFromNetname, GetAllNetClasses)` +- `class MAP_STRING_STRING (Methods: iterator, __iter__, __nonzero__, __bool__, __len__, __iter__, iterkeys, itervalues, iteritems, __getitem__, __delitem__, has_key, keys, values, items, __contains__, key_iterator, value_iterator, __setitem__, asdict, __init__, empty, size, swap, begin, end, rbegin, rend, clear, get_allocator, count, erase, find, lower_bound, upper_bound)` +- `class FP_3DMODEL (Methods: __init__, __eq__)` +- `class FOOTPRINT (Methods: __init__, Serialize, Deserialize, ClassOf, InvalidateGeometryCaches, GetPrivateLayers, SetPrivateLayers, AddNative, RemoveNative, ClearAllNets, FixUuids, GetFpPadsLocalBbox, GetBoundingHull, TextOnly, GetLayerBoundingBox, Pads, GraphicalItems, Zones, Groups, HasThroughHolePads, Models, SetOrientation, GetOrientation, SetLayerAndFlip, SetOrientationDegrees, GetOrientationDegrees, GetFPID, SetFPID, GetFPIDAsString, SetFPIDAsString, GetLibDescription, SetLibDescription, GetKeywords, SetKeywords, GetPath, SetPath, GetSheetname, SetSheetname, GetSheetfile, SetSheetfile, GetFilters, SetFilters, SetLocalClearance, GetLocalSolderMaskMargin, SetLocalSolderMaskMargin, GetLocalSolderPasteMargin, SetLocalSolderPasteMargin, GetLocalSolderPasteMarginRatio, SetLocalSolderPasteMarginRatio, SetLocalZoneConnection, GetLocalZoneConnection, GetAttributes, SetAttributes, SetFlag, IncrementFlag, GetFlag, IsNetTie, GetLocalClearance, GetClearanceOverrides, GetZoneConnectionOverrides, GetNetTiePadGroups, ClearNetTiePadGroups, AddNetTiePadGroup, MapPadNumbersToNetTieGroups, GetNetTiePads, GetLikelyAttribute, MoveAnchorPosition, IsFlipped, GetSide, IsConflicting, IsPlaced, SetIsPlaced, NeedsPlaced, SetNeedsPlaced, LegacyPadsLocked, CheckFootprintAttributes, CheckPads, CheckShortingPads, CheckNetTies, CheckNetTiePadGroups, CheckClippedSilk, BuildNetTieCache, GetNetTieCache, TransformPadsToPolySet, TransformFPShapesToPolySet, TransformFPTextToPolySet, GetContextualTextVars, ResolveTextVar, HitTestAccurate, HitTest, HitTestOnLayer, GetReference, SetReference, GetReferenceAsString, IncrementReference, GetValue, SetValue, GetValueAsString, Value, Reference, GetField, GetFieldById, GetFieldByName, HasFieldByName, GetFieldText, GetFields, ClearFields, AddField, RemoveField, GetNextFieldId, ApplyDefaultSettings, IsBoardOnly, SetBoardOnly, IsExcludedFromPosFiles, SetExcludedFromPosFiles, IsExcludedFromBOM, SetExcludedFromBOM, AllowMissingCourtyard, SetAllowMissingCourtyard, IsDNP, SetDNP, SetFileFormatVersionAtLoad, GetFileFormatVersionAtLoad, FindPadByNumber, GetPad, GetPads, GetPadCount, GetUniquePadCount, GetUniquePadNumbers, GetNextPadNumber, AutoPositionFields, GetTypeName, GetArea, GetLink, SetLink, DuplicateItem, Add3DModel, GetClass, RunOnDescendants, ViewGetLOD, IsLibNameValid, StringLibNameInvalidChars, FootprintNeedsUpdate, SetInitialComments, CoverageRatio, GetCoverageArea, GetInitialComments, GetCourtyard, GetCachedCourtyard, BuildCourtyardCaches, GetEffectiveShape, GetEmbeddedFiles, GetFonts, EmbedFonts, SetComponentClass, SetTransientComponentClassNames, GetTransientComponentClassNames, ClearTransientComponentClassNames, ResolveComponentClassNames, GetComponentClass, GetComponentClassAsString, __eq__, GetFieldsText, GetFieldsShownText, GetFieldText, GetFieldShownText, SetField, HasField, SetFields, GetBoundingBox)` +- `class cmp_drawings (Methods: __call__, __init__)` +- `class cmp_pads (Methods: __call__, __init__)` +- `class cmp_zones (Methods: __call__, __init__)` +- `class VECTOR_FP_3DMODEL (Methods: iterator, __iter__, __nonzero__, __bool__, __len__, __getslice__, __setslice__, __delslice__, __delitem__, __getitem__, __setitem__, pop, append, empty, size, swap, begin, end, rbegin, rend, clear, get_allocator, pop_back, erase, __init__, push_back, front, back, assign, resize, insert, reserve, capacity)` +- `class PYTHON_FOOTPRINT_WIZARD_LIST (Methods: register_wizard, deregister_wizard, __init__)` +- `class PYTHON_ACTION_PLUGINS (Methods: register_action, deregister_action, __init__)` + +## Functions + +- `def _swig_repr(self)` +- `def _swig_setattr_nondynamic_instance_variable(set)` +- `def _swig_setattr_nondynamic_class_variable(set)` +- `def _swig_add_metaclass(metaclass)` +- `def wxSetDefaultPyEncoding(encoding)` +- `def wxGetDefaultPyEncoding()` +- `def NilUuid()` +- `def BaseType(aType)` +- `def IsNullType(aType)` +- `def IsInstantiableType(aType)` +- `def IsEeschemaType(aType)` +- `def IsPcbnewType(aType)` +- `def IsGerbviewType(aType)` +- `def IsPageLayoutEditorType(aType)` +- `def IsMiscType(aType)` +- `def IsTypeCorrect(aType)` +- `def new_clone(aItem)` +- `def IsImperialUnit(aUnit)` +- `def IsMetricUnit(aUnit)` +- `def Mm2mils(aVal)` +- `def Mils2mm(aVal)` +- `def FetchUnitsFromString(aTextValue, aUnits)` +- `def GetText()` +- `def GetLabel()` +- `def FormatAngle(aAngle)` +- `def FormatInternalUnits()` +- `def Mils2IU(aIuScale, mils)` +- `def ToUserUnit(aIuScale, aUnit, aValue)` +- `def StringFromValue()` +- `def MessageTextFromValue()` +- `def MessageTextFromMinOptMax(aIuScale, aUnits, aValue)` +- `def FromUserUnit(aIuScale, aUnit, aValue)` +- `def DoubleValueFromString()` +- `def ValueFromString()` +- `def SearchHelpFileFullPath(aBaseName)` +- `def EnsureFileDirectoryExists(aTargetFullFileName, aBaseFilename, aReporter)` +- `def EnsureFileExtension(aFilename, aExtension)` +- `def ExpandEnvVarSubstitutions(aString, aProject)` +- `def ExpandTextVars()` +- `def GetGeneratedFieldDisplayName(aSource)` +- `def IsGeneratedField(aSource)` +- `def ResolveUriByEnvVars(aUri, aProject)` +- `def TimestampDir(aDirPath, aFilespec)` +- `def WarnUserIfOperatingSystemUnsupported()` +- `def StrPrintf()` +- `def SafeReadFile(aFilePath, aReadType)` +- `def colorRefs()` +- `def __eq__(lhs, rhs)` +- `def __ne__(lhs, rhs)` +- `def __lt__(lhs, rhs)` +- `def __lshift__(aStream, aColor)` +- `def GetBuildVersion()` +- `def GetBaseVersion()` +- `def GetPlatformGetBitnessName()` +- `def GetSemanticVersion()` +- `def GetMajorMinorVersion()` +- `def GetMajorMinorPatchVersion()` +- `def GetBuildDate()` +- `def GetCommitHash()` +- `def GetMajorMinorPatchTuple()` +- `def IsNightlyVersion()` +- `def SetOpenGLInfo(aRenderer, aVendor, aVersion)` +- `def GetVersionInfoData(aTitle, aHtml, aBrief)` +- `def ToGalLayer(aInteger)` +- `def LayerName(aLayer)` +- `def IsValidLayer(aLayerId)` +- `def IsPcbLayer(aLayer)` +- `def IsExternalCopperLayer(aLayerId)` +- `def IsInnerCopperLayer(aLayerId)` +- `def IsNonCopperLayer(aLayerId)` +- `def IsCopperLayer()` +- `def IsViaPadLayer(aLayer)` +- `def IsHoleLayer(aLayer)` +- `def IsSolderMaskLayer(aLayer)` +- `def IsUserLayer(aLayerId)` +- `def IsFrontLayer(aLayerId)` +- `def IsBackLayer(aLayerId)` +- `def IsCopperLayerLowerThan(aLayerA, aLayerB)` +- `def FlipLayer(aLayerId, aCopperLayersCount)` +- `def GetNetnameLayer(aLayer)` +- `def IsNetnameLayer(aLayer)` +- `def IsZoneFillLayer(aLayer)` +- `def IsPadCopperLayer(aLayer)` +- `def IsViaCopperLayer(aLayer)` +- `def IsClearanceLayer(aLayer)` +- `def IsDCodeLayer(aLayer)` +- `def CopperLayerToOrdinal(aLayer)` +- `def BoardLayerFromLegacyId(aLegacyId)` +- `def Map3DLayerToPCBLayer(aLayer)` +- `def MapPCBLayerTo3DLayer(aLayer)` +- `def ToLAYER_ID(aLayer)` +- `def GetUnLoadableWizards()` +- `def GetWizardsSearchPaths()` +- `def GetWizardsBackTrace()` +- `def LoadPluginModule(Dirname, ModuleName, FileName)` +- `def LoadPlugins(bundlepath, userpath, thirdpartypath)` +- `def BOX2ISafe()` +- `def KiROUND()` +- `def SHAPE_TYPE_asString(a)` +- `def Cast_to_SHAPE_ARC(_self)` +- `def Cast_to_SHAPE_CIRCLE(_self)` +- `def Cast_to_SHAPE_COMPOUND(_self)` +- `def Cast_to_SHAPE_LINE_CHAIN(_self)` +- `def Cast_to_SHAPE_POLY_SET(_self)` +- `def Cast_to_SHAPE_RECT(_self)` +- `def Cast_to_SHAPE_SEGMENT(_self)` +- `def Cast_to_SHAPE_SIMPLE(_self)` +- `def IsUTF8(aString)` +- `def PlotDrawingSheet()` +- `def GetDefaultPlotExtension(aFormat)` +- `def GetBoard()` +- `def LoadBoard()` +- `def NewBoard(aFileName)` +- `def GetSettingsManager()` +- `def CreateEmptyBoard()` +- `def SaveBoard(aFileName, aBoard, aSkipSettings)` +- `def GetFootprintLibraries()` +- `def GetFootprints(aNickName)` +- `def ExportSpecctraDSN()` +- `def ExportVRML(aFullFileName, aMMtoWRMLunit, aIncludeUnspecified, aIncludeDNP, aExport3DFiles, aUseRelativePaths, a3D_Subdir, aXRef, aYRef)` +- `def ImportSpecctraSES()` +- `def ExportFootprintsToLibrary()` +- `def Refresh()` +- `def UpdateUserInterface()` +- `def GetUserUnits()` +- `def GetCurrentSelection()` +- `def FocusOnItem(aItem, aLayer)` +- `def IsActionRunning()` +- `def WriteDRCReport(aBoard, aFileName, aUnits, aReportAllTrackErrors)` +- `def GetLanguage()` +- `def Cast_to_BOARD_ITEM(base)` +- `def Cast_to_PCB_TEXT(arg1)` +- `def Cast_to_PCB_TEXTBOX(arg1)` +- `def Cast_to_PCB_DIM_ALIGNED(arg1)` +- `def Cast_to_PCB_DIM_ORTHOGONAL(arg1)` +- `def Cast_to_PCB_DIM_LEADER(arg1)` +- `def Cast_to_PCB_DIM_CENTER(arg1)` +- `def Cast_to_PCB_DIM_RADIAL(arg1)` +- `def Cast_to_FOOTPRINT(arg1)` +- `def Cast_to_PCB_GROUP(arg1)` +- `def Cast_to_PCB_SHAPE(arg1)` +- `def Cast_to_PCB_MARKER(arg1)` +- `def Cast_to_BOARD(arg1)` +- `def Cast_to_PAD(arg1)` +- `def Cast_to_PCB_TRACK(arg1)` +- `def Cast_to_PCB_VIA(arg1)` +- `def Cast_to_PCB_ARC(arg1)` +- `def Cast_to_ZONE(arg1)` +- `def Cast_to_PCB_TARGET(arg1)` +- `def Cast_to_PCB_TABLE(arg1)` +- `def Cast_to_PCB_REFERENCE_IMAGE(arg1)` +- `def PrintZoneConnection(aConnection)` +- `def InvokeNonCopperZonesEditor(aParent, aSettings, aConvertSettings)` +- `def InvokeCopperZonesEditor(aCaller, aSettings, aConvertSettings)` +- `def InvokeRuleAreaEditor(aCaller, aSettings, aBoard, aConvertSettings)` +- `def GetFlippedAlignment()` +- `def ToHAlignment(x)` +- `def GetPluginForPath(libname)` +- `def FootprintEnumerate(libname)` +- `def FootprintLoad(libname, name, preserveUUID)` +- `def FootprintSave(libname, module)` +- `def FootprintDelete(libname, name)` +- `def FootprintLibCreate(libname)` +- `def FootprintLibDelete(libname)` +- `def FootprintIsWritable(libname)` +- `def ToMM(iu)` +- `def FromMM(mm)` +- `def ToMils(iu)` +- `def FromMils(mils)` +- `def PutOnGridMM(value, gridSizeMM)` +- `def PutOnGridMils(value, gridSizeMils)` +- `def wxSizeMM(mmx, mmy)` +- `def wxSizeMils(mmx, mmy)` +- `def wxPointMM(mmx, mmy)` +- `def wxPointMils(mmx, mmy)` +- `def VECTOR2I_MM(mmx, mmy)` +- `def VECTOR2I_Mils(mmx, mmy)` +- `def wxRectMM(x, y, wx, wy)` +- `def wxRectMils(x, y, wx, wy)` +- `def Version()` +- `def FullVersion()`