rmcanany / SolidEdgeHousekeeper

Utility for finding annoying little errors in your Solid Edge project
MIT License
23 stars 10 forks source link

Interactive Edit -- Add a pause button and a countdown timer #78

Closed rmcanany closed 2 months ago

rmcanany commented 6 months ago

So a user can quickly review unfamiliar files.

rmcanany commented 3 months ago

Maybe add the ability to launch a command, for example open the variable table. The user would select the command from a dropdown on the task options.

rmcanany commented 2 months ago

@farfilli @ChrisClems

I'm playing around with the countdown timer idea. See below a way NOT to do it. Do you know of a better way? I've been reading about Async/Await, but am having trouble wrapping my head around it.

    Private Sub FormEditInteractively_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        PauseTimer()
    End Sub

    Private Sub PauseTimer()
        For i = 0 To 10
            Application.DoEvents()
            Me.ProgressBar1.Value = 10 * i
            System.Threading.Thread.Sleep(500)
        Next
    End Sub
rmcanany commented 2 months ago

Never mind. I got something working, though I don't completely understand it.


    Private Sub FormEditInteractively_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        PauseTimer()
    End Sub

    Private Async Sub PauseTimer()
        Await CallMethodAsync()
    End Sub

    Private Async Function CallMethodAsync() As Task(Of System.Threading.Tasks.Task)
        Me.ProgressBar1.Value = 0
        Me.ProgressBar1.Maximum = 1000
        Await ExecuteMethodAsync()
    End Function

    Private Async Function ExecuteMethodAsync() As Task(Of System.Threading.Tasks.Task)
        For percentComplete As Integer = 0 To 1000 - 1
            Await System.Threading.Tasks.Task.Delay(10)
            ProgressBar1.Increment(1)
        Next
    End Function

    Private Sub PauseButton_Click(sender As Object, e As EventArgs) Handles PauseButton.Click
        Me.ProgressBar1.Visible = False
    End Sub
ChrisClems commented 2 months ago

Sorry, I've been swamped with work. Got three huge automation projects and the most I'm getting out of it is a long list of IRs to report to Siemens for broken APIs.

If I understand the use case correctly, you want to iterate through files, bringing them to the active window for the user to perform an action, continuing to the next file based on a countdown with a pause button?

I'm afraid I don't know enough about the old .NET framework GUI libraries (especially in the context of VB) to provide much practical code. I would accomplish this by spinning off a thread for the timer and using a ManualResetEvent to interact with the timer in my own projects. The way I understand WinForms, multi-threading is handled differently.

I see there's a Timer class that might be useful for making this cleaner and a little more in-line with WinForms conventions. I couldn't explain this code in detail without doing a much deeper dive, but I put this together from some Googling. I think the only UI thread blocking part of this is whatever you perform on each tick so if your progress bar update is light weight, you shouldn't need to deal with threading and async/await.

Private countdown As Integer
Private WithEvents Timer As New Windows.Forms.Timer()

countdown = 30
Timer.Interval = 1000

Private Sub btnPause_Click(sender As System.Object, e As System.EventArgs) Handles btnPause.Click
    Timer.Stop()
End Sub

Private Sub btnResume_Click(sender As System.Object, e As System.EventArgs) Handles btnResume.Click 
    Timer.Start()
End Sub

Private Sub Timer_Tick(sender As System.Object, e As System.EventArgs) Handles Timer.Tick
    countdown -= 1
    'Do something every tick if you want
    If countdown <= 0 Then
        Timer.Stop()
        PerformAction()
    End If
End Sub
rmcanany commented 2 months ago

Oh, that's slick! I read about the timer thing, but missed the fact it is firing off events like that. That's what I'll use. Thank you!

The world thanks you for filing IRs on broken APIs, by the way.

farfilli commented 2 months ago

Why not add a " Done " button the user presses when the manual task is completed? Something like the green check when you finish with a feature. :white_check_mark:

rmcanany commented 2 months ago

Yeah, it kinda has that now, but not as attractive. I'll look into it.

The idea of the countdown was to let me quickly review a bunch of files without interaction. If something caught my eye, I wanted the ability to pause and investigate further. Not sure it's a real improvement, but I wanted to try it out.

The other thing I want to add is the ability to launch a command (via StartCommand). I've had several requests for obscure things like clicking the 'Update on file save' checkbox on the Physical Properties dialog. Rather than creating separate Tasks for such (often one-time) things, I thought it might be almost as good to do most of the work and let the user finish the job.

ChrisClems commented 2 months ago

I didn't dig into what you've already written for this, but one of our drafters I think has a really great use case for this so I was mentally walking myself through the process.

I think for interactive edit, an event listener that moves on to the next part in the list would be hugely helpful in addition to the timer. I imagine a workflow where I need to add a text profile to a few dozen parts. That's something very difficult to do via the API. The part opens. I perform my edits. I save the part. Housekeeper watches for the status of the part to either be saved or closed.

Watch for AfterDocumentSave(theDocument = currentHousekeeperDoc) and assume that since we've made a save, we're done with the edit. Close the document and open the next one in the list. This one is nice because a simple ctrl+S is enough to move the process to the next document. It breaks if you want to make multiple saves before moving on.

Watch for BeforeDocumentClose(theDocument = currentHousekeeperDoc) then just open the next one. This one doesn't break on multiple saves but there's no hotkey to close a SE document so it's a bit less streamlined.

Have a button in Housekeeper that saves and moves on to the next doc. This one is less ideal as the other two options allow you to remain within SE without breaking stride, but it's faster than waiting for a timer to finish.

As I type this up, I'm now imagining a dropdown that has some pre-defined events that the API supports. You can choose an event that the API will fire as your trigger to move on to the next part in the list. Off the top of my head only Save and Close make sense, but I'm sure someone could think of others that would be useful.

I've never done event listener work outside of the SE process, but Spy supports them so there must be some elegant way to handle it. I might dig into that code to see if I can decipher how it's done. I assume some async/await function.

Another great use case I can think of for this would be updating flat pattern treatments to simplify bsplines on a large group of parts. There is absolutely no functionality in the API to change this setting. It's manually configured per part.

rmcanany commented 2 months ago

Yeah, exactly. Your guy is going to love this. Housekeeper already serves up files one at a time, so I don't think we need that part.

In the image, you can see what I have so far. The ComboBox populates the command IDs, which are hidden under the list in the image. Choosing Custom sets them all to zero. In that case, a user would manually enter any valid command ID they find in the API docs. I'll place a link to those enumerations in my documentation.

Options edit_interactively

Dialog edit_interactively_dialog

rmcanany commented 2 months ago

I got this working more or less like I wanted now. @ChrisClems if your guy tries this out, I would welcome any feedback he has. That includes on the documentation, which he can access with the blue question mark on the Task's options panel.

rmcanany commented 2 months ago

Closing as complete.