i'm a beginner in learning actionscript and i'm seeing examples to learn from them. in the following lines, what should i add or remove so i can hide or not show system messages? and what are these lines actually say?
public function set showSystemMsgs(param1:Boolean) : void
{
var _loc:* = this.showSystemMsgs;
if (_loc !== param1)
{
this.showSystemMsgs = param1;
this.dispatchEvent(PropertyChangeEvent.createUpdateEvent(this, "showSystemMsgs", _loc, param1));
}
return;
}
public function get showSystemMsgs() : Boolean
{
return this.showSystemMsgs;
}
public function removeEventListener(param1:String, param2:Function, param3:Boolean = false) : void
{
_bindingEventDispatcher.removeEventListener(param1, param2, param3);
return;
}
If your goal is to understand code, stop reading decompiled code. This is not code meant to be read by humans opposed to what the code looked like before compilation.
There are plenty of resources on pretty much everything available by now, with explanations, comments and readable code.
object.showSystemMsgs = false;
Might work, where object is a reference to an object of the class which you partially posted.
Related
Essentially my problem is that I receive AccessViolationException when I try to programmatically apply more than 2 links to an ITextDocument, if a user has edited the content. I've put together a simple demo app, based on the windows phone (8.1) Blank App template.
I add to the main page:
<StackPanel Margin="19,0,0,0">
<Button
Content="Apply Links"
Click="Button_Click"
/>
<RichEditBox
x:Name="RtfBox"
Height="300"
Loaded="RtfBox_Loaded"
Margin="0,0,19,0"
TextWrapping="Wrap"
/>
</StackPanel>
And to the code behind for the same page I add (using statements not included):
private void RtfBox_Loaded(object sender, RoutedEventArgs e)
{
//RtfBox.Document.SetText(TextSetOptions.None, "Links to demo, example, test. More links to demo, demo, example, test and test.");
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var pages = new Dictionary<Guid, string> { { Guid.NewGuid(), "demo" }, { Guid.NewGuid(), "example" }, { Guid.NewGuid(), "test" } };
// NOTE: Avoid performance implications of many small updates
RtfBox.Document.BatchDisplayUpdates();
ITextRange range;
foreach (var page in pages)
{
var link = string.Format("\"richtea.demo://pages/{0}\"", page.Key);
var skip = 0;
while ((range = RtfBox.Document.GetRange(skip, TextConstants.MaxUnitCount)).FindText(page.Value, TextConstants.MaxUnitCount, FindOptions.None) != 0)
{
if (range.Link == "")
{
// TODO: Stop this throw exceptions
System.Diagnostics.Debug.WriteLine("Setting text at position {0} to link: '{1}'.", range.StartPosition, link);
range.Link = link;
}
skip = range.EndPosition;
}
}
RtfBox.Document.ApplyDisplayUpdates();
}
If you start this up and type something like "A link to the demo page" and click the button, it becomes a link correctly. You can keep putting the same text and clicking the button and it continues to work.
However if you put in three or more (for some reason for me it's always 3 or more) of the words demo, example or test (my keywords) and hit the button, it errors on an AccessViolationException on setting range.Link = link. It's worth noting if you check while debugging, the range.Link property has actually been set.
More interestingly, if you uncomment RtfBox_Loaded's contents, and run the app and click the button right away, it handles it fine. So it seems to relate to the selection having been set on the RichEditBox? I've tried disabling the control before applying the links, but that's not helped me.
Some other things which have made it harder for me to diagnose the issue here include:
It seems to work more often if I'm debugging line by line, so might be timing related too
I can't use the ITextDocument not on the UI thread it seems (the COM object fails to cast) so while it seems async might be a better approach, I haven't succeeded at it here.
Also for the record, the reason I'm attempting to do all the updates on mass, rather than as the user types them is that I don't want to deal with the cleanup when notes are renamed or deleted, and I don't really want those links in at edit time or saved, but I could live with the later.
This solution was posted on the MSDN forums by Eric Fleck and worked for me:
RtfBox.Document.Selection.StartPosition = RtfBox.Document.Selection.EndPosition = range.StartPosition;
range.Link = link;
RtfBox.Document.Selection.StartPosition = RtfBox.Document.Selection.EndPosition = range.EndPosition;
It seemed that it's important to do it around each link being set, because unless I'm very much mistaken I tried this before updating all my links and it didn't help.
I'm not yet using the ability to restore the selection to it's original location, but I might want to in the future, so I made this little utility class. Also so that I can wrap places like these in a using() block for a bit of syntactic sugar.
public static class ITextDocumentExtensions
{
public static IDisposable SuppressSelection(this ITextDocument document)
{
var start = document.Selection.StartPosition;
var end = document.Selection.EndPosition;
var disposable = new ActionDisposable(() => document.Selection.SetRange(start, end));
document.Selection.SetRange(0, 0);
return disposable;
}
private sealed class ActionDisposable : IDisposable
{
private readonly Action dispose;
public ActionDisposable(Action dispose)
{
this.dispose = dispose;
}
public void Dispose()
{
dispose();
}
}
}
Which allows me to write
using (RtfBox.Document.SuppressSelection())
{
range.Link = link;
}
When running swfs through decompilers (my own swfs, not somebody else's), I've noticed a lot of mention of certain variables:
_loc_1
_loc_2
_loc_3
.
.
.
_loc_n
As in the following example:
private function templateFilterFunction(param1) : Boolean
{
var _loc_2:* = false;
if (filterFunction != null)
{
_loc_2 = filterFunction(param1, typedText);
}
return _loc_2;
}
Alright, so these are apparently just normal variables then, right? And they may have had more descriptive names in the original AS3 code, but that's been lost in the bytecode, and now we have the same variables as before, just with non-descript names, right?
Not exactly. For instance:
package
{
public class SomeClass extends Object
{
public var var1:Number;
public var var2:Number;
public var var3:Number;
public function SomeClass(param1:Number, param2:Number, param3:Number)
{
if (!_loc_5)
{
if (!_loc_4)
{
var3 = param1;
if (!_loc_4)
{
var1 = param2;
}
}
}
var2 = param3;
return;
}// end function
}
}
These aren't declared. But they're not exactly members of Object either, and I've never seen them outside of a swf decompilation. What are they then? Thanks.
Not sure about that particular piece of code, but the decompilers I've used (as far as I remember) all call the local variables loc_n, local_n or something like that.
I think you already know why. Local variables are created and pushed onto the execution stack; they are not referenced from outside the local scope and since they are not callable by name, their names are just whipped off the bytecode. (The object pointed by the variable could be allocated on the heap and live outside the scope of the function, however, but that's not the point here).
Now, another thing you might be aware of is that some bytecode generated by the compiler just doesn't traslate to actionscript code. There are things that can be done in bytecode that are not really possible in AS code; an example, off the top of my head: the "dup" opcode (duplicates a value and pushes it onto the stack). There are others (jumps, noops, etc). Reversing this to the original source code is sometimes not possible.
There are other interesting cases such as loops. You may notice that a particular decompiler tends to generate "for loops" (or "while loops") regardless of whether the source code had a for or a while. That's because loops are a higher level construct that are usually implemented in bytcode as conditional jumps. If you want to reverse the bytecode to AS code, you just have to pick a flavor because the loop (as an AS construct) is just not there.
That said, I've seen some decompilers (can't remember which one now) generating invalid or non-sensical source code. To me, that's the case in the example you post. I may be wrong but it seems like the _loc_5 and _loc_4 vars are just gibberish and the original code must be something like:
public function SomeClass(param1:Number, param2:Number, param3:Number):void
{
var var3:Number = param1;
var var1:Number = param2;
var var2:Number = param3;
}
So, I have successfully grabbed a value out of an XML document and set it into a separate class called "AddCommas." The trace functions have shown me that it sets properly.
For more details, my objective is to take the language indicator ("fr" for french or "en" for english), set it inside the appropriate class and into a variable I will use. Now, I am using this variable to be used in an if statement; which will help me format a number properly (commas, decimals, spaces) per the clients request.
However, my problem is when I try to get the value to use it. It always comes back as Null. I have placed traces all over my program trying to pinpoint when this happens, but I cannot find it. Here's the code...
The pull from the XML file and into the set (this works fine, but I am adding it for your benefit in case I missed something)
public var commaHold = new AddCommas();
localLanguage = xmlObj.localLanguage;
trace("localLanguage + " + localLanguage);
commaHold.setLanguage(localLanguage); // Set Language
//More code follows...
This is the set function istelf...
public function setLanguage(localLanguage:String){
langHold = localLanguage;
trace("Set Language = " + langHold); //This always shows a successful set
}
Now am I wrong in thinking that in AS3, once langHold in my AddCommas class has been set I should be able to use it without calling a get within the function I am using the If Statement in, right? Such as this?
var language = langHold;
if (language == "en"){
trace("Language is = " + language); // More code follows afterwards and as of now, this shows NULL
Now, I have attempted plenty of Get functions to add the language variable in the call itself to this function and it's always the same. Am I missing some fundamentals here?
Thank you very much for your time.
If you expect a string comparison you need to use quotes, unless en is a String variable since langHold is a String, like:
if (language == "en"){
Consider modifying the set function to use the as3 keyword like:
private var _language:String;
public function set language(value:String):void {
_language = value;
//do other stuff here if necessary, put a breakpoint on the line above
}
public function get language():String{
return _language;
//put a breakpoint on the line above
}
You should be able to see when any instance of your class has the property changed. The only other issue I can think of is it is not the same instance of the class and therefore doesn't share the property value you set earlier. In the debugger you can check the "hashCode" or "address" it shows for this to see if it changes when it hits the breakpoints.
Here's a sample Singleton structure in AS3 (this all goes in one file):
package com.shaunhusain.singletonExample
{
public class SingletonExample
{
private static var instance:SingletonExample;
public static function getIntance():SingletonExample
{
if( instance == null ) instance = new SingletonExample( new SingletonEnforcer() );
return instance;
}
/**
*
* #param se Blocks creation of new managers instead use static method getInstance
*/
public function SingletonExample(se:SingletonEnforcer)
{
}
}
}
internal class SingletonEnforcer {public function SingletonEnforcer(){}}
using this single shared instance from any other class would look something like this:
private var singletonInstance:SingletonExample = SingletonExample.getInstance();
ShaunHusain's theory of using a Singleton was the perfect solution I needed. However, his code gave me a bizarre 1061 error and my format and code appeared to be error free. Regardless, I looked up another way to use a Singleton as follows that worked perfectly for me. Honestly, Shaun's code should work for anyone and I have no idea why it wasn't. I am perfectly willing to admit that it was probably a typo on my end that I just did not see.
I ended up embedding the Set and Get within the Singletons class and used it as an intermediary to hold the information I needed. It worked perfectly.
package chart {
import chart.*;
//
public class StaticInstance {
private static var instance:StaticInstance;
private static var allowInstantiation:Boolean;
private var language:String;
public static function getInstance():StaticInstance {
if (instance == null) {
allowInstantiation = true;
instance = new StaticInstance();
allowInstantiation = false;
}
return instance;
}
public function StaticInstance():void {
if (!allowInstantiation) {
throw new Error("Error: Instantiation failed: Use StaticInsance.getInstance() instead of new.");
}
}
public function setLanguage(_language:String):void{
language = _language;
trace("language set = " + language);
}
public function getLanguage():String{
return language;
}
}
}
This code allowed me to hold the data and call upon it again from two different classes. It's a very hack job instead of just being able to pass on the variable from function to function, but in my case we didn't create this file, we are modifying it and attempting to do things beyond the original scope of the project.
Thanks again for your help Shaun! I hope this helps other people!
I'm writing a genetic fitness program, and I'm currently writing some code that will calculate the 'fitness' value of each organism.
I'm trying to call a function that initializes each genotype;
function random_genotype_initialisation():void
{
//stuff
}
By using the typical method-calling I'm used to in C# and Java;
random_genotyoe_initialisation();
However this returns the error: "TypeError: Error #1010: A term is undefined and has no properties."
I've looked elsewhere for help, and I've found suggestions such as declaring a variable and 'calling' that.
var rep = replicate_new_generation();
rep.call();
Any suggestions?
I assume there's an undefined value inside your random_genotype_initialisation() function. You are correct, you call a function in as3 same as in java/c/c++/c#/js/etc.
The snippet is a bit wrong because you store the result of the replcate_new_generation into rep, but that is a void function, so rep will be void and therefore not have call():
var rep = replicate_new_generation();//rep = void at this point
rep.call();//call does not exist for rep
Do you mean ?
var rep:Function = replicate_new_generation;
rep.call();
Which is same as: replicate_new_generation();
If the error is generating within the function perhaps you should post the body
of the function as well ?
C# is VERY similar to AS3, I have no idea what you are trying to do or why your code did not work since you didn't provide a very good example. But you can call functions directly as long as it is accessible just in any normal way.
say, inside a class you have:
class Boo {
private function foo():void {
trace("bar");
}
public function foobar():void {
foo();
}
}
class FoobarCaller {
public function FoobarCaller (){
var asdf:Boo = new Boo();
asdf.foobar();
}
}
that works, just as it would in C# or any other "standard coding language. However, without a better question it's impossible to say what it is you have done wrong
my question is simple, yet I couldn't find any answer of it in the net, maybe it's impossible to do...
The thing is that I have an ActionScript 3.0 application, and wanted to include a little one-line size textbox which showed all the trace() calls and such, which are shown in the console.
Has anyone got any idea of how can it be done? I would really appreciate it, as I have a full project with traces on it that I'd like to show, and it's now when I'm finishing that I'm realising I don't know how to do it :P
Of course not everything is lost, as I could just do my own class that showed there the messages, but it would be cleanier, and quicker not to have to replace all the trace() calls for my new class and method.
Regards and thanks in advance :)
I just did this last week.
There are logging frameworks for Flex out there. A shame, though, that Flex's logging only works in Debug mode. If you search SO for Flex logging you'll find various suggestions. None of them are amazing, IMO.
Finally I rolled my own by just creating a Log class with a static function that acts as a proxy for trace.
Something like:
public static myTrace(... args) : void { ... }
Then you just forward the args to trace but also to whatever other destination you want (e.g. an array of strings + dates) that you can then display in the log window.
Incidentally, I also used SwfAddress to trigger the log window whenever a certain parameter is added to the URL. Very handy.
Oh, what the heck.. here's the class. It just keeps the last 100 strings and there's also a "dump" function that you can invoke if you want to send the data to your server or just quickly print the entire history.
public class Log
{
public static var lines : ArrayList = new ArrayList();
public static const MAX_LINES : int = 100;
private static function logLine(line : String) : void
{
while (lines.length > MAX_LINES)
lines.removeItemAt(0);
lines.addItem({"line" : line, "time" : new Date()});
}
public static function logDump() : String
{
var ret : String = "";
for each (var entry : Object in lines.source)
{
ret = (entry.time as Date).toUTCString() + " " + entry.line + "\n" + ret;
}
return ret;
}
public static function debug(...args) : void
{
trace(args);
var line : String = "";
for (var i : int = 0; i < args.length; i++)
if (args[i] != null)
line += args[i].toString();
logLine(line);
}
}
Alternatively, you can use the ASDebugger
http://labs.flexperiments.nl/asdebugger-20-a-real-time-debugger-and-editor/
ASDebugger.debug( 'shallala' );
ASDebugger.debug_prop( variable );
Try to avoid using the debug display object option. The debugger can crash for complex objects (especially in flex)
You can probably do a simple replacement of 'trace(' to 'ASDebugger.debug('