Coverage for /home/pi/Software/model-railway-signalling/model_railway_signals/editor/configure_signal_tab2.py: 100%

267 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2024-04-05 17:29 +0100

1#------------------------------------------------------------------------------------ 

2# Functions and sub Classes for the Edit Signal "Interlocking" Tab 

3# 

4# Makes the following external API calls to other editor modules: 

5######################################################################################################### 

6# Note that we need to use the 'objects.section_exists' function as the the library 'section_exists' 

7# function will not work in edit mode as the Track Section library objects don't exist in edit mode 

8# To be addressed in a future software update when the Track Sections functionality is re-factored 

9######################################################################################################### 

10# objects.section_exists(id) - To see if the track section exists (local) ########################## 

11# 

12# Makes the following external API calls to library modules: 

13# signals_common.sig_exists(id) - To see if the instrument exists (local or remote) 

14# points.point_exists(id) - To see if the point exists (local) 

15# block_instruments.instrument_exists(id) - To see if the instrument exists (local or remote) 

16# track_sections.section_exists(id) - To see if the track section exists #################### 

17# 

18# Inherits the following common editor base classes (from common): 

19# common.check_box 

20# common.int_item_id_entry_box 

21# common.str_int_item_id_entry_box 

22# common.signal_route_selections 

23# common.point_interlocking_entry 

24# 

25#------------------------------------------------------------------------------------ 

26 

27import tkinter as Tk 

28 

29from . import common 

30from . import objects ################################################################################## 

31 

32from ..library import points 

33from ..library import signals_common 

34from ..library import block_instruments 

35from ..library import track_sections 

36 

37#------------------------------------------------------------------------------------ 

38# Class for a route interlocking group (comprising 6 points, a signal and an instrument) 

39# Uses the common point_interlocking_entry class for each point entry 

40# Public class instance methods provided are: 

41# "validate" - validate the current entry box values and return True/false 

42# "set_route" - will set the route elements (points, sig_ahead and inst_ahead) 

43# Note that we also need the current item id for validation of the sig_ahead 

44# "get_route" - returns the last "valid" values (points, sig_ahead and inst_ahead) 

45# "enable_route" - enables all points, sig_ahead and inst_ahead selections 

46# "disable_route" - disables all points, sig_ahead and inst_ahead selections 

47# "enable_sig_ahead" - enables the Sig ahead selections (if the route is enabled) 

48# "disable_sig_ahead" - disables the Sig ahead selections 

49# "enable_block_ahead" - enables the block ahead selections (if the route is enabled) 

50# "disable_block_ahead" - disables the block ahead selections 

51#------------------------------------------------------------------------------------ 

52 

53class interlocking_route_group: 

54 def __init__(self, parent_frame, label:str): 

55 # These are the 'item exists' functions for validation 

56 signal_exists_function = signals_common.sig_exists 

57 instrument_exists_function = block_instruments.instrument_exists 

58 point_exists_function = points.point_exists 

59 # Create a frame for this UI element (always packed into the parent frame) 

60 self.frame = Tk.Frame(parent_frame) 

61 self.frame.pack() 

62 # Create the lable and the point interlocking entry elements (these are 

63 # packed LEFT in the frame by the parent class when created) 

64 self.label = Tk.Label(self.frame, anchor='w', width=5, text=label) 

65 self.label.pack(side = Tk.LEFT) 

66 tool_tip = "Specify any points that need to be set and locked before the signal can be cleared for the route" 

67 self.p1 = common.point_interlocking_entry(self.frame, point_exists_function, tool_tip) 

68 self.p2 = common.point_interlocking_entry(self.frame, point_exists_function, tool_tip) 

69 self.p3 = common.point_interlocking_entry(self.frame, point_exists_function, tool_tip) 

70 self.p4 = common.point_interlocking_entry(self.frame, point_exists_function, tool_tip) 

71 self.p5 = common.point_interlocking_entry(self.frame, point_exists_function, tool_tip) 

72 self.p6 = common.point_interlocking_entry(self.frame, point_exists_function, tool_tip) 

73 # Create the signal ahead and instrument ahead elements (always packed) 

74 self.label1 = Tk.Label(self.frame, text=" Sig:") 

75 self.label1.pack(side=Tk.LEFT) 

76 self.sig = common.str_int_item_id_entry_box(self.frame, exists_function=signal_exists_function, 

77 tool_tip = "Specify the next signal along the specified route - This "+ 

78 "can be a local signal ID or a remote signal ID (in the form 'Node-ID') "+ 

79 " which has been subscribed to via MQTT networking") 

80 self.sig.pack(side=Tk.LEFT) 

81 self.label2 = Tk.Label(self.frame, text=" Blk:") 

82 self.label2.pack(side=Tk.LEFT) 

83 self.block = common.int_item_id_entry_box(self.frame, exists_function=instrument_exists_function, 

84 tool_tip="Specify the ID of the Block Instrument on the local schematic which "+ 

85 "controls access to the block section along the specified route") 

86 self.block.pack(side=Tk.LEFT) 

87 

88 def validate(self): 

89 # Validate everything - to highlight ALL validation errors in the UI 

90 valid = True 

91 if not self.p1.validate(): valid = False 

92 if not self.p2.validate(): valid = False 

93 if not self.p3.validate(): valid = False 

94 if not self.p4.validate(): valid = False 

95 if not self.p5.validate(): valid = False 

96 if not self.p6.validate(): valid = False 

97 if not self.sig.validate(): valid = False 

98 if not self.block.validate(): valid = False 

99 return(valid) 

100 

101 def enable_sig_ahead(self): 

102 self.sig.enable1() 

103 

104 def disable_sig_ahead(self): 

105 self.sig.disable1() 

106 

107 def enable_block_ahead(self): 

108 self.block.enable1() 

109 

110 def disable_block_ahead(self): 

111 self.block.disable1() 

112 

113 def enable_route(self): 

114 self.p1.enable() 

115 self.p2.enable() 

116 self.p3.enable() 

117 self.p4.enable() 

118 self.p5.enable() 

119 self.p6.enable() 

120 self.sig.enable() 

121 self.block.enable() 

122 

123 def disable_route(self): 

124 self.p1.disable() 

125 self.p2.disable() 

126 self.p3.disable() 

127 self.p4.disable() 

128 self.p5.disable() 

129 self.p6.disable() 

130 self.sig.disable() 

131 self.block.disable() 

132 

133 def set_route(self, interlocking_route:[[int,bool],str,int], item_id:int): 

134 # A route comprises: [[p1, p2, p3, p4, p5, p6, p7], sig_id, instrument_id] 

135 # Each point element in the point list comprises [point_id, point_state] 

136 # Note that the sig ID can be a local or remote Signal (so a string) 

137 self.p1.set_value(interlocking_route[0][0]) 

138 self.p2.set_value(interlocking_route[0][1]) 

139 self.p3.set_value(interlocking_route[0][2]) 

140 self.p4.set_value(interlocking_route[0][3]) 

141 self.p5.set_value(interlocking_route[0][4]) 

142 self.p6.set_value(interlocking_route[0][5]) 

143 # Note we pass in the current signal_id for validation (to prevent selection) 

144 self.sig.set_value(interlocking_route[1], item_id) 

145 self.block.set_value(interlocking_route[2]) 

146 

147 def get_route(self): 

148 # A route comprises: [[p1, p2, p3, p4, p5, p6, p7], sig_id, instrument_id] 

149 # Each point element in the point list comprises [point_id, point_state] 

150 # Note that the sig ID can be a local or remote Signal (so a string) 

151 route = [ [ self.p1.get_value(), 

152 self.p2.get_value(), 

153 self.p3.get_value(), 

154 self.p4.get_value(), 

155 self.p5.get_value(), 

156 self.p6.get_value() ], 

157 self.sig.get_value(), 

158 self.block.get_value() ] 

159 return (route) 

160 

161#------------------------------------------------------------------------------------ 

162# Class for a route interlocking frame  

163# Uses the base interlocking_route_group class from above 

164# "validate" - validate the current entry box values and return True/false 

165# "set_routes" - will set all route selections (points, sigs_ahead & insts_ahead) 

166# Note that we also need the current item id for validation of the sig_ahead 

167# "get_routes" - returns the last "valid" values (points, sigs_ahead & insts_ahead) 

168# "enable_sig_ahead" - enables the Sig ahead selections (if the route is enabled) 

169# "disable_sig_ahead" - disables the Sig ahead selections 

170# "enable_block_ahead" - enables the block ahead selections (if the route is enabled) 

171# "disable_block_ahead" - disables the block ahead selections 

172#------------------------------------------------------------------------------------ 

173 

174class interlocking_route_frame: 

175 def __init__(self, parent_window, parent_object): 

176 # Create a Label Frame for the UI element (packed by the creating function/class) 

177 self.frame = Tk.LabelFrame(parent_window, text= "Signal routes and point interlocking") 

178 # Create the route elements (sign, sub, dist) - these are packed in class instancees 

179 self.main = interlocking_route_group(self.frame, "Main") 

180 self.lh1 = interlocking_route_group(self.frame, "LH1") 

181 self.lh2 = interlocking_route_group(self.frame, "LH2") 

182 self.rh1 = interlocking_route_group(self.frame, "RH1") 

183 self.rh2 = interlocking_route_group(self.frame, "RH2") 

184 

185 def validate(self): 

186 # Validate everything - to highlight ALL validation errors in the UI 

187 valid = True 

188 if not self.main.validate(): valid = False 

189 if not self.lh1.validate(): valid = False 

190 if not self.lh2.validate(): valid = False 

191 if not self.rh1.validate(): valid = False 

192 if not self.rh2.validate(): valid = False 

193 return(valid) 

194 

195 def set_routes(self, interlocking_frame:[[[[int,bool],],str,int]], item_id:int): 

196 # An interlocking frame comprises a list of routes: [main, lh1, lh2, rh1, rh2] 

197 # Each route comprises: [[p1, p2, p3, p4, p5, p6, p7], sig_id, instrument_id] 

198 # Each point element in the point list comprises [point_id, point_state] 

199 # Note that the sig ID can be a local or remote Signal (so a string) 

200 # Note also we pass in the current signal_id for validation (to prevent selection) 

201 self.main.set_route(interlocking_frame[0], item_id) 

202 self.lh1.set_route(interlocking_frame[1], item_id) 

203 self.lh2.set_route(interlocking_frame[2], item_id) 

204 self.rh1.set_route(interlocking_frame[3], item_id) 

205 self.rh2.set_route(interlocking_frame[4], item_id) 

206 

207 def get_routes(self): 

208 # An interlocking frame comprises a list of routes: [main, lh1, lh2, rh1, rh2] 

209 # Each route comprises: [[p1, p2, p3, p4, p5, p6, p7], sig_id, instrument_id] 

210 # Each point element in the point list comprises [point_id, point_state] 

211 # Note that the sig ID can be a local or remote Signal (so a string) 

212 return ( [ self.main.get_route(), 

213 self.lh1.get_route(), 

214 self.lh2.get_route(), 

215 self.rh1.get_route(), 

216 self.rh2.get_route() ] ) 

217 

218 def enable_sig_ahead(self): 

219 self.main.enable_sig_ahead() 

220 self.lh1.enable_sig_ahead() 

221 self.lh2.enable_sig_ahead() 

222 self.rh1.enable_sig_ahead() 

223 self.rh2.enable_sig_ahead() 

224 

225 def disable_sig_ahead(self): 

226 self.main.disable_sig_ahead() 

227 self.lh1.disable_sig_ahead() 

228 self.lh2.disable_sig_ahead() 

229 self.rh1.disable_sig_ahead() 

230 self.rh2.disable_sig_ahead() 

231 

232 def enable_block_ahead(self): 

233 self.main.enable_block_ahead() 

234 self.lh1.enable_block_ahead() 

235 self.lh2.enable_block_ahead() 

236 self.rh1.enable_block_ahead() 

237 self.rh2.enable_block_ahead() 

238 

239 def disable_block_ahead(self): 

240 self.main.disable_block_ahead() 

241 self.lh1.disable_block_ahead() 

242 self.lh2.disable_block_ahead() 

243 self.rh1.disable_block_ahead() 

244 self.rh2.disable_block_ahead() 

245 

246#------------------------------------------------------------------------------------ 

247# Class for a conflicting signal UI Element (for interlocking) 

248# uses multiple instances of the common signal_route_selection_element 

249# Public class instance methods provided by this class are: 

250# "set_values" - Populates the list of interlocked signals and their routes  

251# Note that we also need the current item id for validation 

252# "get_values" - Returns the list of interlocked signals and their routes 

253# "enable_route" - Enables/loads all selections for the route 

254# "disable_route" - Disables/blanks all selections for the route 

255# "validate" - Validates all Entry boxes (Signals exist and not current ID)  

256#------------------------------------------------------------------------------------ 

257 

258class conflicting_signals_element(): 

259 def __init__(self, parent_frame, parent_object, label:str): 

260 # Theis is the functions used to validate that the entered signal ID exists 

261 exists_function = signals_common.sig_exists 

262 # Create the Label Frame for the UI element (packed/unpacked on enable/disable)  

263 self.frame = Tk.LabelFrame(parent_frame, text=label+" - interlocking with conflicting signals") 

264 self.frame.pack(padx=2, pady=2, fill='x') 

265 # create two frames - each frame will hold two conflicting signals 

266 self.subframe1 = Tk.Frame(self.frame) 

267 self.subframe1.pack() 

268 self.subframe2 = Tk.Frame(self.frame) 

269 self.subframe2.pack() 

270 tool_tip = "Specify any signals/routes that would conflict with this signal route" 

271 self.sig1 = common.signal_route_selections(self.subframe1, read_only=False, 

272 tool_tip = tool_tip,exists_function=exists_function) 

273 self.sig1.frame.pack(side=Tk.LEFT, padx=5) 

274 self.sig2 = common.signal_route_selections(self.subframe1, read_only=False, 

275 tool_tip = tool_tip, exists_function=exists_function) 

276 self.sig2.frame.pack(side=Tk.LEFT, padx=5) 

277 self.sig3 = common.signal_route_selections(self.subframe2, read_only=False, 

278 tool_tip = tool_tip, exists_function=exists_function) 

279 self.sig3.frame.pack(side=Tk.LEFT, padx=5) 

280 self.sig4 = common.signal_route_selections(self.subframe2, read_only=False, 

281 tool_tip = tool_tip, exists_function=exists_function) 

282 self.sig4.frame.pack(side=Tk.LEFT, padx=5) 

283 

284 def validate(self): 

285 # Validate everything - to highlight ALL validation errors in the UI 

286 valid = True 

287 if not self.sig1.validate(): valid = False 

288 if not self.sig2.validate(): valid = False 

289 if not self.sig3.validate(): valid = False 

290 if not self.sig4.validate(): valid = False 

291 return(valid) 

292 

293 def enable_route(self): 

294 self.sig1.enable() 

295 self.sig2.enable() 

296 self.sig3.enable() 

297 self.sig4.enable() 

298 

299 def disable_route(self): 

300 self.sig1.disable() 

301 self.sig2.disable() 

302 self.sig3.disable() 

303 self.sig4.disable() 

304 

305 def set_values(self, sig_route:[[int,[bool,bool,bool,bool,bool]],], item_id): 

306 # each sig_route comprises [sig1, sig2, sig3, sig4] 

307 # each signal comprises [sig_id, [main, lh1, lh2, rh1, rh2]] 

308 # Where each route element is a boolean value (True or False) 

309 self.sig1.set_values(sig_route[0], item_id) 

310 self.sig2.set_values(sig_route[1], item_id) 

311 self.sig3.set_values(sig_route[2], item_id) 

312 self.sig4.set_values(sig_route[3], item_id) 

313 

314 def get_values(self): 

315 # each sig_route comprises [sig1, sig2, sig3, sig4] 

316 # each signal comprises [sig_id, [main, lh1, lh2, rh1, rh2]] 

317 # Where each route element is a boolean value (True or False) 

318 return ( [self.sig1.get_values(), 

319 self.sig2.get_values(), 

320 self.sig3.get_values(), 

321 self.sig4.get_values()] ) 

322 

323#------------------------------------------------------------------------------------ 

324# Class for a conflicting signal frame UI Element (for interlocking) 

325# uses multiple instances of the common signal_route_selection_element 

326# Public class instance methods provided by this class are: 

327# "set_values" - Populates the table of interlocked signal routes 

328# Note that we also need the current item id for validation 

329# "get_values" - Returns the table of interlocked signal routes 

330# "validate" - Validates all entries (Signals exist and not the current ID) 

331#------------------------------------------------------------------------------------ 

332 

333class conflicting_signals_frame(): 

334 def __init__(self, parent_frame, parent_object): 

335 # Create the Label Frame for the UI element (packed by the creating function/class) 

336 self.frame = Tk.LabelFrame(parent_frame, text="Conflicting signals not locked by the above point selections") 

337 self.main = conflicting_signals_element(self.frame, parent_object, "MAIN Route") 

338 self.lh1 = conflicting_signals_element(self.frame, parent_object, "LH1 Route") 

339 self.lh2 = conflicting_signals_element(self.frame, parent_object, "LH2 Route") 

340 self.rh1 = conflicting_signals_element(self.frame, parent_object, "RH1 Route") 

341 self.rh2 = conflicting_signals_element(self.frame, parent_object, "RH2 Route") 

342 

343 def validate(self): 

344 # Validate everything - to highlight ALL validation errors in the UI 

345 valid = True 

346 if not self.main.validate(): valid = False 

347 if not self.lh1.validate(): valid = False 

348 if not self.lh2.validate(): valid = False 

349 if not self.rh1.validate(): valid = False 

350 if not self.rh2.validate(): valid = False 

351 return(valid) 

352 

353 def set_values(self, sig_interlocking_routes:[[[int,[bool,bool,bool,bool,bool]],],], item_id:int): 

354 # sig_interlocking_routes comprises a list of sig_routes [main,lh1,lh2,rh1,rh2] 

355 # each sig_route comprises a list of interlocked signals [sig1, sig2, sig3, sig4] 

356 # each interlocked signal entry comprises [sig_id, [main, lh1, lh2, rh1, rh2]] 

357 # sig_id is the interlocked signal and the interlocked routes are True/False 

358 self.main.set_values(sig_interlocking_routes[0], item_id) 

359 self.lh1.set_values(sig_interlocking_routes[1], item_id) 

360 self.lh2.set_values(sig_interlocking_routes[2], item_id) 

361 self.rh1.set_values(sig_interlocking_routes[3], item_id) 

362 self.rh2.set_values(sig_interlocking_routes[4], item_id) 

363 

364 def get_values(self): 

365 # sig_interlocking_routes comprises a list of sig_routes [main,lh1,lh2,rh1,rh2] 

366 # each sig_route comprises a list of interlocked signals [sig1, sig2, sig3, sig4] 

367 # each interlocked signal entry comprises [sig_id, [main, lh1, lh2, rh1, rh2]] 

368 # sig_id is the interlocked signal and the interlocked routes are True/False 

369 return ( [self.main.get_values(), 

370 self.lh1.get_values(), 

371 self.lh2.get_values(), 

372 self.rh1.get_values(), 

373 self.rh2.get_values() ] ) 

374 

375#------------------------------------------------------------------------------------ 

376# Class for a interlocked track sections group UI Element (for interlocking) 

377# Provides a label frame containing 3 track section entry boxes for a signal route 

378# Public class instance methods provided by this class are: 

379# "set_route" - Populates the list of interlocked track sections for the group 

380# "get_route" - Returns the list of interlocked track sections for the route 

381# "enable_route" - Enables/loads all selections for the route 

382# "disable_route" - Disables/blanks all selections for the route 

383# "validate" - Validates all Entries (Track Section exists on schematic) 

384#------------------------------------------------------------------------------------ 

385 

386class interlocked_sections_group: 

387 def __init__(self, parent_frame, label:str): 

388 self.frame = Tk.LabelFrame(parent_frame, text=label) 

389 self.frame.pack(side=Tk.LEFT, padx=8, pady=2) 

390 tool_tip = "Specify any track sections along the route that will lock this signal when occupied by another train" 

391 ######################################################################################################### 

392 # Note that we need to use the 'objects.section_exists' function as the the library 'section_exists' 

393 # function will not work in edit mode as the Track Section library objects don't exist in edit mode 

394 # To be addressed in a future software update when the Track Sections functionality is re-factored 

395 ######################################################################################################### 

396 self.t1 = common.int_item_id_entry_box(self.frame, exists_function=objects.section_exists, tool_tip=tool_tip) 

397 self.t1.pack(side = Tk.LEFT) 

398 self.t2 = common.int_item_id_entry_box(self.frame, exists_function=objects.section_exists, tool_tip=tool_tip) 

399 self.t2.pack(side = Tk.LEFT) 

400 self.t3 = common.int_item_id_entry_box(self.frame, exists_function=objects.section_exists, tool_tip=tool_tip) 

401 self.t3.pack(side = Tk.LEFT) 

402 

403 def validate(self): 

404 # Validate everything - to highlight ALL validation failures in the UI 

405 valid = True 

406 if not self.t1.validate(): valid = False 

407 if not self.t2.validate(): valid = False 

408 if not self.t3.validate(): valid = False 

409 return(valid) 

410 

411 def enable_route(self): 

412 self.t1.enable() 

413 self.t2.enable() 

414 self.t3.enable() 

415 

416 def disable_route(self): 

417 self.t1.disable() 

418 self.t2.disable() 

419 self.t3.disable() 

420 

421 def set_route(self, interlocked_route:[int,int,int]): 

422 # An interlocked_route comprises: [t1,t2,t3] Where each element is 

423 # the ID of a track section the signal is to be interlocked with 

424 self.t1.set_value(interlocked_route[0]) 

425 self.t2.set_value(interlocked_route[1]) 

426 self.t3.set_value(interlocked_route[2]) 

427 

428 def get_route(self): 

429 # An interlocked_route comprises: [t1,t2,t3] Where each element is 

430 # the ID of a track section the signal is to be interlocked with 

431 interlocked_route = [ self.t1.get_value(), self.t2.get_value(), self.t3.get_value() ] 

432 return(interlocked_route) 

433 

434#------------------------------------------------------------------------------------ 

435# Class for a interlocked track sections frame UI Element 

436# uses multiple instances of the interlocked_sections_group class 

437# Public class instance methods provided by this class are: 

438# "set_routes" - Populates the list of interlocked track sections for each route 

439# "get_routes" - Returns the list of interlocked track sections for each route 

440# "validate" - Validates all Entries(Track sections exist on the schematic) 

441#------------------------------------------------------------------------------------ 

442 

443class interlocked_sections_frame(): 

444 def __init__(self, parent_frame): 

445 # Create the Label Frame for the UI element (packed by the creating function/class) 

446 self.frame = Tk.LabelFrame(parent_frame, text="Interlock with occupied track sections") 

447 # Create a subframe to pack everything into so the contents are centered 

448 self.subframe = Tk.Frame(self.frame) 

449 self.subframe.pack() 

450 # Create the Interlocked group UI elements (one for each signal route) 

451 self.main = interlocked_sections_group(self.subframe, "Main") 

452 self.lh1 = interlocked_sections_group(self.subframe, "LH1") 

453 self.lh2 = interlocked_sections_group(self.subframe, "LH2") 

454 self.rh1 = interlocked_sections_group(self.subframe, "RH1") 

455 self.rh2 = interlocked_sections_group(self.subframe, "RH2") 

456 

457 def validate(self): 

458 # Validate everything - to highlight ALL validation failures in the UI 

459 valid = True 

460 if not self.main.validate(): valid = False 

461 if not self.lh1.validate(): valid = False 

462 if not self.lh2.validate(): valid = False 

463 if not self.rh1.validate(): valid = False 

464 if not self.rh2.validate(): valid = False 

465 return(valid) 

466 

467 def set_routes(self, interlocked_sections): 

468 # interlocked_sections comprises a list of routes: [MAIN, LH1, LH2, RH1, RH2] 

469 # Each route element contains a list of interlocked sections for that route [t1,t2,t3] 

470 # Each entry is the ID of a track section the signal is to be interlocked with 

471 self.main.set_route(interlocked_sections[0]) 

472 self.lh1.set_route(interlocked_sections[1]) 

473 self.lh2.set_route(interlocked_sections[2]) 

474 self.rh1.set_route(interlocked_sections[3]) 

475 self.rh2.set_route(interlocked_sections[4]) 

476 

477 def get_routes(self): 

478 # Returned list comprises a list of routes: [MAIN, LH1, LH2, RH1, RH2] 

479 # Each route element contains a list of interlocked sections for that route [t1,t2,t3] 

480 # Each entry is the ID of a track section the signal is to be interlocked with 

481 return ( [self.main.get_route(), 

482 self.lh1.get_route(), 

483 self.lh2.get_route(), 

484 self.rh1.get_route(), 

485 self.rh2.get_route() ] ) 

486 

487#------------------------------------------------------------------------------------ 

488# Class for the Distant 'interlock with home signals ahead" ui element 

489# Inherits from common.check_box class (get_value/set_value/enable/disable) 

490# Only enabled if the signal type is a distant signal (semaphore or colour light) 

491#------------------------------------------------------------------------------------ 

492 

493class interlock_with_signals_ahead(common.check_box): 

494 def __init__(self, parent_frame): 

495 # Create the Label Frame for the UI element (packed by the creating function/class) 

496 self.frame = Tk.LabelFrame(parent_frame, text="Distant signal interlocking") 

497 super().__init__(self.frame, label="Interlock distant with all home signals ahead", 

498 tool_tip="Select to lock the distant signal at CAUTION if any home signals "+ 

499 "on the route ahead are at DANGER (if the distant signal is CLEAR it "+ 

500 "will remain unlocked so it can be returned to CAUTION at any time)") 

501 self.pack() 

502 

503#------------------------------------------------------------------------------------ 

504# Top level Class for the Signal Interlocking Tab 

505#------------------------------------------------------------------------------------ 

506 

507class signal_interlocking_tab: 

508 def __init__(self, parent_tab, parent_object): 

509 self.interlocking = interlocking_route_frame(parent_tab, parent_object) 

510 self.interlocking.frame.pack(padx=2, pady=2, fill='x') 

511 self.interlocked_sections = interlocked_sections_frame(parent_tab) 

512 self.interlocked_sections.frame.pack(padx=2, pady=2, fill='x') 

513 self.conflicting_sigs = conflicting_signals_frame(parent_tab, parent_object) 

514 self.conflicting_sigs.frame.pack(padx=2, pady=2, fill='x') 

515 self.interlock_ahead = interlock_with_signals_ahead(parent_tab) 

516 self.interlock_ahead.frame.pack(padx=2, pady=2, fill='x') 

517 

518#############################################################################################