Public demo snapshot of an in-house pyRevit extension for precast concrete shop-ticket QC (37 checks / 46 checklist rows) and a standalone panel handling solver (PCI Chapter 8). - No client, job, plant or product data: knowledge layers ship as structural templates only. - Ticket QC's model-read escalation targets a LAN model server endpoint (configurable), not a cloud provider. - Built from the private development repo via tools/make_dist.py.
This commit is contained in:
+167
@@ -0,0 +1,167 @@
|
||||
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="Project Config"
|
||||
ShowInTaskbar="False"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
SizeToContent="Height"
|
||||
Width="880" MaxHeight="940" MinHeight="380"
|
||||
ResizeMode="CanResize"
|
||||
Background="#f6f7f9">
|
||||
|
||||
<!--
|
||||
THE WINDOW IS CHROME ONLY. Every field is built in `script.py` from
|
||||
`vibe.configform`, because the field list is data: it depends on which
|
||||
build of `configmodel` this Revit session is holding, on which stages
|
||||
the job has, and on how many checklist items are muted. A XAML
|
||||
DataTemplate would have had to know all three.
|
||||
|
||||
What lives here is what does not change: the four module boxes, the
|
||||
reason line every job-layer write needs, and the four buttons. Every
|
||||
x:Name below is looked up by name in `script.py`, and every Click
|
||||
handler names a method on the window class. `tests/test_configform.py`
|
||||
parses this file and that one together and fails if the two have
|
||||
drifted, which is the only check available for a window that cannot be
|
||||
opened without Revit.
|
||||
|
||||
EVERY MODULE IS AN Expander, NOT A GroupBox, AND STARTS COLLAPSED. The
|
||||
owner's ruling, 2026-09-01, verbatim in `script.py`'s own comment (kept
|
||||
out of THIS file because the no-Chinese-in-the-XAML test below scans
|
||||
every byte of it, comments included, and not only the strings a build
|
||||
would render): every section folds, and folded is the default; open
|
||||
the one you came to change, adjust it, done. `IsExpanded="False"` here
|
||||
is the fallback for the very first time this window opens in a
|
||||
session; `script.py` overrides it per module from
|
||||
`vibe.configform.remembered_expanded`, which is the ONLY thing that
|
||||
may reopen one on its own, since a module the owner left open a minute
|
||||
ago staying open is a convenience, and a module opening because it
|
||||
carries a value is not this window's call to make silently, which is
|
||||
why the header text says so instead (see `configform.is_modified` /
|
||||
`modified_count`, and `script.py`'s use of them building each
|
||||
Header).
|
||||
|
||||
No double hyphen anywhere in this comment: XML forbids it inside a
|
||||
comment, and the test above catches it as a parse error rather than as
|
||||
a window that will not load.
|
||||
-->
|
||||
|
||||
<Window.Resources>
|
||||
<!-- No FontWeight or Foreground here: a GroupBox passes both down to
|
||||
its CONTENT, so setting them to style the header would make every
|
||||
label and every note in the box bold as well. The rows set their
|
||||
own weight and colour in script.py. -->
|
||||
<Style TargetType="{x:Type GroupBox}">
|
||||
<Setter Property="Margin" Value="0,0,0,10"/>
|
||||
<Setter Property="Padding" Value="6"/>
|
||||
<Setter Property="BorderBrush" Value="#c9d2dd"/>
|
||||
</Style>
|
||||
<!-- The four modules are Expanders now, not GroupBoxes; see the
|
||||
note above this Window's own opening comment. Same border,
|
||||
same spacing, so folding cost nothing visually except the
|
||||
fold itself. -->
|
||||
<Style TargetType="{x:Type Expander}">
|
||||
<Setter Property="Margin" Value="0,0,0,10"/>
|
||||
<Setter Property="Padding" Value="6"/>
|
||||
<Setter Property="BorderBrush" Value="#c9d2dd"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="Background" Value="White"/>
|
||||
</Style>
|
||||
<Style TargetType="{x:Type Button}">
|
||||
<Setter Property="Padding" Value="10,3,10,3"/>
|
||||
<Setter Property="MinWidth" Value="76"/>
|
||||
<Setter Property="Margin" Value="0,0,6,0"/>
|
||||
</Style>
|
||||
<Style TargetType="{x:Type TextBox}">
|
||||
<Setter Property="Padding" Value="3,2,3,2"/>
|
||||
<Setter Property="VerticalContentAlignment" Value="Center"/>
|
||||
</Style>
|
||||
</Window.Resources>
|
||||
|
||||
<DockPanel Margin="14">
|
||||
|
||||
<!-- The sentence that used to be cut off by a 36-pixel Label. It
|
||||
wraps here, because there is room here. -->
|
||||
<TextBlock x:Name="header"
|
||||
DockPanel.Dock="Top"
|
||||
TextWrapping="Wrap"
|
||||
FontWeight="Bold"
|
||||
Foreground="#2c3e50"
|
||||
Margin="0,0,0,4"
|
||||
Text="Project Config"/>
|
||||
<TextBlock x:Name="subheader"
|
||||
DockPanel.Dock="Top"
|
||||
TextWrapping="Wrap"
|
||||
Foreground="#5a6b7d"
|
||||
Margin="0,0,0,10"
|
||||
Text=""/>
|
||||
|
||||
<Border DockPanel.Dock="Bottom"
|
||||
Background="#eef1f5"
|
||||
BorderBrush="#c9d2dd"
|
||||
BorderThickness="1"
|
||||
Padding="8"
|
||||
Margin="0,10,0,0">
|
||||
<StackPanel>
|
||||
<TextBlock x:Name="status"
|
||||
TextWrapping="Wrap"
|
||||
Foreground="#2c3e50"
|
||||
Margin="0,0,0,6"
|
||||
Text="Nothing changed yet."/>
|
||||
<DockPanel Margin="0,0,0,8">
|
||||
<TextBlock DockPanel.Dock="Left"
|
||||
VerticalAlignment="Center"
|
||||
Width="150"
|
||||
Text="Why (written into the file)"/>
|
||||
<TextBox x:Name="reason_box" Height="24"/>
|
||||
</DockPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button x:Name="save_button"
|
||||
Content="Save to the job layer"
|
||||
MinWidth="150"
|
||||
Click="save_click"/>
|
||||
<Button x:Name="cancel_button"
|
||||
Content="Close"
|
||||
Click="cancel_click"/>
|
||||
<Button x:Name="openfile_button"
|
||||
Content="Open the job file"
|
||||
MinWidth="130"
|
||||
Click="openfile_click"/>
|
||||
<Button x:Name="fullview_button"
|
||||
Content="Full view"
|
||||
Click="fullview_click"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto"
|
||||
HorizontalScrollBarVisibility="Disabled">
|
||||
<StackPanel>
|
||||
<Expander x:Name="group_file_path" Header="File paths"
|
||||
IsExpanded="False">
|
||||
<StackPanel x:Name="panel_file_path"/>
|
||||
</Expander>
|
||||
<Expander x:Name="group_lifting" Header="Lifting and handling"
|
||||
IsExpanded="False">
|
||||
<StackPanel x:Name="panel_lifting"/>
|
||||
</Expander>
|
||||
<Expander x:Name="group_ticketqc" Header="Ticket QC"
|
||||
IsExpanded="False">
|
||||
<StackPanel x:Name="panel_ticketqc"/>
|
||||
</Expander>
|
||||
<Expander x:Name="group_job_knowledge" Header="Job knowledge"
|
||||
IsExpanded="False">
|
||||
<StackPanel x:Name="panel_job_knowledge"/>
|
||||
</Expander>
|
||||
<Border Background="#fff8e6"
|
||||
BorderBrush="#e0c98a"
|
||||
BorderThickness="1"
|
||||
Padding="8">
|
||||
<TextBlock x:Name="rest_line"
|
||||
TextWrapping="Wrap"
|
||||
Foreground="#6b5a20"
|
||||
Text="Everything else: edit the config file directly."/>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
</DockPanel>
|
||||
</Window>
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
title: Project Config
|
||||
# DEV. A fresh IronPython engine for every press: `lib/vibe` is re-imported
|
||||
# on each click, so an edit to a module this button uses is visible without
|
||||
# a Revit restart. It trades press latency (engine construction instead of
|
||||
# engine reuse) for restart-freedom. Second-hottest button on this ribbon --
|
||||
# 14 commits to configmodel/configpage/configform/configdump/knowledge in the
|
||||
# seven days to 2026-08-30.
|
||||
#
|
||||
# Read docs/architecture-migration.md section 8 before trusting or removing
|
||||
# this. Two things it says that are not obvious: pyRevit's DEFAULT is already
|
||||
# a clean engine, and this extension gets one today only because
|
||||
# extension.json has no `url:` and so is never registered as a package --
|
||||
# add a url and every button silently switches to the shared engine. This key
|
||||
# is the pin against that, not a new capability.
|
||||
#
|
||||
# REMOVE IT PER BUTTON as that button stabilises: delete the two lines below.
|
||||
engine:
|
||||
clean: true
|
||||
# No tooltip and no author on purpose. pyRevit renders both on hover;
|
||||
# the owner wants nothing there. Guarded by
|
||||
# WillTools.extension/tests/test_button_tooltips.py -- do not add them back.
|
||||
#
|
||||
# One line: this button is a row in a `.pulldown`, and a pulldown row renders
|
||||
# as text beside a 16px icon. A `\n` in it has nowhere to go. The dropdown
|
||||
# grows to fit the longest row, so the title may say what it means.
|
||||
#
|
||||
# "Project Config" rather than plain "Config": the button one level up is
|
||||
# already called Config, and a Config row inside a Config button reads like
|
||||
# a mistake even though the two name tables never collide.
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 6.4 KiB |
+1453
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user