Observer event on closing model


#1

I’m developing an extension that uses a WebDialog to input its parameters. I use an AppObserver to watch for when a new model opens up, or if the user changes focus from one model to another (I’m on MAC). But if I have a single model open and I close it, without exiting the application, I can’t find any observer event to notify my webdialog that its time to close.

Specifically, AppObserver has no “onClose” method. This wouldn’t manifest on windows, assuming sketchup just closes itself on that platform. But on MAC it would be a big help.

Anyone know if there is a better way to accomplish this?


#2

there is a way to do this and there was a lot of posts over at SketchUcation on the “best” way…

I’ll see if I can find some examples…

If you post your observer code it may narrow things down…

john


#3

EDIT: Disregard. (Steve corrected below. I thought you wanted an App close callback.)

It is named Sketchup::AppObserver#onQuit

(FYI, The onClose callback belongs to Sketchup::InstanceObserver.)


#4

Dan, on the Mac’s MDI, onQuit doesn’t fire if you have more than one model open. It fires only when you quit the app altogether.


#5

Also, during the application shutdown cycle (after the user is prompted to save the model if it’s modified flag is true,) the model object is then destroyed and the Sketchup::ModelObserver#onDeleteModel or Sketchup::ModelObserver#onEraseAll callback will probably fire. (I think it was the latter on PC, but I do not have a Mac, so test for both.)

EDIT: Should perhaps apply also when just closing just a document child window on Mac’s MDI interface.


#6

Oh, sorry. Misread his post. Thought he did quit SU. OK then, my 2nd post should be more appropriate.


#7

from memory…
getting an active model handle and polling it from js in the webdialog was successful…

jhon


#8

The problem is that on a Mac you can close all of the open models without quitting the app (and then use File->New to start a new model). When the app shutdown causes events to fire, the original question is moot because the web dialogs are going away along with SketchUp anyway!

@john_drivenupthewall I’d be interested in the details if you can dig them up.


#9

In this case:

@model.valid?

should return false.

Sketchup::active_model

should return nil.

@model == Sketchup::active_model

should return false.


#10

All true, but how does the OP’s ruby detect when to make one of these tests? I’m still struggling to find an event that will fire so he knows to check what happened.

And for the benefit of Windows users who may be wondering what the heck we’re talking about, on the Mac the app can be running a) with no model open at all, b) with just one model open and active, or c) with multiple models open and one of them the active_model. Closing a model, even the last one open, does not cause the SketchUp app to quit.


#11

[quote=“DanRathbun, post:5, topic:18371, full:true”]
Also, during the application shutdown cycle (after the user is prompted to save the model if it’s modified flag is true,) the model object is then destroyed and the Sketchup::ModelObserver#onDeleteModel or Sketchup::ModelObserver#onEraseAll callback will probably fire. (I think it was the latter on PC, but I do not have a Mac, so test for both.)[/quote]

I had added a edit note:

Should perhaps apply also when just closing just a document child window on Mac’s MDI interface.


#12

I installed a model observer but no luck. With this class:

  class AttrModObserver < Sketchup::ModelObserver
    def initialize(dialog)
      @dialog = dialog
      printf("Registering Mod:%s\n", dialog)
    end
    def onEraseAll(model)
      printf("Erasing:%s self:%s\n", model, self)
    end
    def onDeleteModel(model)
      printf("Deleting:%s self:%s\n", model, self)
    end
    def onExplode(model)
      printf("Exploding:%s self:%s\n", model, self)
    end
  end #AttrModObserver

I see the correct output when the observer is instantiated. I can also fire an event when I explode a component. But sadly, I don’t get events for onEraseAll or onDeleteModel when the model window is closed. Strangely, I don’t even get onEraseAll when I do select-all, followed by a delete. Maybe that’s because there are still unseen component definitions in the model though.


#13

I have tried to find this subject on SketchUcation but no luck so far. If you find anything, a link here would be great.


#14

I can’t find the webDialog version of ‘Apple_Pudding’ or my test scripts anywhere,

must have all been in PM’s with bad titles…

so I’ll hack together a new ‘proof’ using a setInterval(function()

john


#15

bit messy but works…
type proof to run after pasting into ‘Ruby Console’…

open a new window or close current skp to close the dialog…

#Sketchup.send_action("openRubyConsole:")
def proof      # just type proof after loading
su_Id = true
def cur_title
	begin
	model = Sketchup.active_model()
	su_Id = model.definitions.object_id()
	has_title = model.title()
	add_title = "Unsaved_" + su_Id.to_s

	# First check if there's an active model name
		if has_title.length > 1 then
			current_title = has_title
		else
		 current_title = add_title
		end
	rescue
		 # .. handle error
		 #  UI.messagebox("You need an open .skp for this to work")
			puts "You need an open .skp for this to work"
	else
	#check
			puts "model name is: " + current_title.to_s
			ensure
		#	puts "current_title " + "is a " + defined? current_title
		#	puts "Congratulations  no errors!"
	end
	current_title
end
current_title = cur_title	
#--------------------------------------------------------------------
# tls_dlg =
u_top = <<U_TOP
<html><head>
<title>
U_TOP

my_string = <<MY_STRING
</title>
</head>
<body>
<div class="" id="">
MY_STRING

u_tail = <<U_TAIL
</div>
            <script>
           myVar = setInterval(function(){window.location='skp:auto2ruby@' + document.title;}, 1000);
            </script>
</body>
</html>
U_TAIL

all = u_top + current_title + my_string + current_title + u_tail

 @dlg = UI::WebDialog.new(current_title, false,
   "9th", 400, 600, 15, 15, false, true)
# @dlg.set_background_color("rgba(127, 127, 127, 0.3)")
 @dlg.set_html(all)
 @dlg.add_action_callback("auto2ruby") {|d,params|
 id = cur_title
  if  id != params
# p id == params
# else
 @dlg.execute_script("clearInterval(myVar); window.close();")
end
 }
 @dlg.show_modal
end


#16

The AppObserver method:
onActivateModel(model)
only works on MAC.
It is different from:
onOpenModel(model)
It kicks in when the ‘focus’ changes from one model to another inside one SketchUp.
On a PC models always open each in a single instance of SketchUp.
So for MAC only…
Unfortunately onActivateModel only takes the newly activated model as the argument.
However, what you could do is set up an Array [let’s say called @models] that has each new model added to it.
When the user changes their active model you know the previously active model - it’s @models[-1]
If the user changes their active model you delete any reference to it in @models and then push that now active model onto the end of the Array.
So if there’s data associated with that model you can access it at that changeover.
You could store data on a model by model basis using a hash that’s shared by all models [instead of a simple ‘array’]…
@models_hash[model1] >>> some data
@models_hash[model2] >>> some different data
etc ?


#17

Thanks for taking the time, John. Being a bit of a javascript noob, seeing how setInterval works was very helpful. Although I hate polling in general, this method does work and all my dialogs eventually get cleaned up regardless of whether the user closes the webdialog first or closed the model window first.

I think the correct answer would be for SU to add a method to call when the user closes a model window. That seems like a sensible event for cleanup hooks, in general.

I am also amazed that users on Windows can only have one model open at a time. That seems very limiting coming from a MAC, Linux background.


#18

I set the polling to be quite lazy at 2000, I would run at 100 after removing the puts it triggers…

all the observers are polling as well so it’s not that expensive…

In a more long winded version I was using it to change the webDialog based on the active model model, i.e. the content and title changed…

must be somewhere…

BTW: I often open a second instance of SU and run them concurrently the “Windows” way…

john


#19

Are you sure about this? I thought observers were event-driven, i.e. that the event engine distributes method calls to observers that are registered. Vastly more efficient than having them poll to see if anything has happened.


#20

It’s not true about number of models open on PC being limited to one.

On a MAC every model’s SKP is opened in one instance of SketchUp.
On a PC each model’s SKP is opened in a separate instance of SketchUp.
However, when opened in the same session the ‘ruby’ side can be contrived to carry over between SKPs…