Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Events
Videos
Audiobooks
Packt Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials

7018 Articles
article-image-organizing-backbone-applications-structure-optimize-and-deploy
Packt
21 Jan 2014
9 min read
Save for later

Organizing Backbone Applications - Structure, Optimize, and Deploy

Packt
21 Jan 2014
9 min read
(For more resources related to this topic, see here.) Creating application architecture The essential premise at the heart of Backbone has always been to try and discover the minimal set of data-structuring (Models and Collections) and user interface (Views and URLs) primitives that are useful when building web applications with JavaScript. Jeremy Ashkenas, creator of Backbone.js, Underscore.js, and CoffeeScript As Jeremy mentioned, Backbone.js has no intention, at least in the near future, to raise its bar to provide application architecture. Backbone will continue to be a lightweight tool to produce the minimal features required for web development. So, should we blame Backbone.js for not including such functionality even though there is a huge demand for this in the developer community? Certainly not! Backbone.js only yields the set of components that are necessary to create the backbone of an application and gives us complete freedom to build the app architecture in whichever way we want. If working on a significantly large JavaScript application, remember to dedicate sufficient time to planning the underlying architecture that makes the most sense. It's often more complex than you may initially imagine. Addy Osmani, author of Patterns For Large-Scale JavaScript Application Architecture So, as we start digging into more detail on creating an application architecture, we are not going to talk about trivial applications or something similar to a to-do-list app. Rather, we will investigate how to structure a medium- or large-level application. After discussions with a number of developers, we found that the main issue they face here is that there are several methodologies the online blog posts and tutorials offer to structure an application. While most of these tutorials talk about good practices, it becomes difficult to choose exactly one from them. Keeping that in mind, we will explore a number of steps that you should follow to make your app robust and maintainable in the long run. Managing a project directory This is the first step towards creating a solid app architecture. We have already discussed this in detail in the previous sections. If you are comfortable using another directory layout, go ahead with it. The directory structure will not matter much if the rest of your application is organized properly. Organizing code with AMD We will use RequireJS for our project. As discussed earlier, it comes with a bunch of facilities such as the following: Adding a lot of script tags in one HTML file and managing all of the dependencies on your own may work for a medium-level project, but will gradually fail for a large-level project. Such a project may have thousands of lines of code; managing a code base of that size requires small modules to be defined in each individual file. With RequireJS, you do not need to worry about how many files you have—you just know that if the standard is followed properly, it is bound to work. The global namespace is never touched and you can freely give the best names to something that matches with it the most. Debugging the RequireJS modules is a lot easier than other approaches because you know what the dependencies and path to each of them are in every module definition. You can use r.js, an optimization tool for RequireJS that minifies all the JavaScript and CSS files, to create the production-ready build. Setting up an application For a Backbone app, there must be a centralized object that will hold together all the components of the application. In a simple application, most people generally just make the main router work as the central object. But that will surely not work for a large application and you need an Application object that should work as the parent component. This object should have a method (mostly init()) that will work as the entry point to your application and initialize the main router along with the Backbone history. In addition, either your Application class should extend Backbone.Events or it should include a property that points to an instance of the Backbone.Events class. The benefit of doing this is that the app or Backbone.Events instance can act as a central event aggregator, and you can trigger application-level events on it. A very basic Application class will look like the following code snippet: // File: application.js define([ 'underscore', 'backbone', 'router' ], function (_, Backbone, Router) { // the event aggregator var PubSub = _.extend({}, Backbone.Events); var Application = function () { // Do useful stuff here } _.extend(Application.prototype, { pubsub: new PubSub(), init: function () { Backbone.history.start(); } }); return Application; }); Application is a simple class with an init() method and a PubSub instance. The init() method acts as the starting point of the application and PubSub works as the application-level event manager. You can add more functionality to the Application class, such as starting and stopping modules and adding a region manager for view layout management. It is advisable to keep this class as short as you can. Using the module pattern We often see that intermediate-level developers find it a bit confusing to initially use a module-based architecture. It can be a little difficult for them to make the transition from a simple MVC architecture to a modular MVC architecture. While the points we are discussing in this article are valid for both these architectures, we should always prefer to use a modular concept in nontrivial applications for better maintainability and organization. In the directory structure section, we saw how the module consists of a main.js file, its views, models, and collections all together. The main.js file will define the module and have different methods to manage the other components of that module. It works as the starting point of the module. A simple main.js file will look like the following code: // File: main.js define([ 'app/modules/user/views/userlist', 'app/modules/user/views/userdetails' ], function (UserList, UserDetails) { var myVar; return { initialize: function () { this.showUserList(); }, showUsersList: function () { var userList = new UserList(); userList.show(); }, showUserDetails: function (userModel) { var userDetails = new UserDetails({ model: userModel }); userDetails.show(); } }; }); As you can see, the responsibility of this file is to initiate the module and manage the components of that module. We have to make sure that it handles only parent-level tasks; it shouldn't contain a method that one of its views should ideally have. The concept is not very complex, but you need to set it up properly in order to use it for a large application. You can even go for an existing app and module setup and integrate it with your Backbone app. For instance, Marionette provides an application infrastructure for Backbone apps. You can use its inbuilt Application and Module classes to structure your application. It also provides a general-purpose Controller class—something that doesn't come with the Backbone library but can be used as a mediator to provide generic methods and work as a common medium among the modules. You can also use AuraJS (https://github.com/aurajs/aura), a framework-agonistic event-driven architecture developed by Addy Osmani (http://addyosmani.com) and many others; it works quite well with Backbone.js. A thorough discussion on AuraJS is beyond the scope of this book, but you can grab a lot of useful information about it from its documentation and examples (https://github.com/aurajs/todomvc). It is an excellent boilerplate tool that gives your app a kick-start and we highly recommend it, especially if you are not using the Marionette application infrastructure. The following are a few benefits of using AuraJS ; they may help you choose this framework for your application: AuraJS is framework-agnostic. Though it works great with Backbone.js, you can use it for your JavaScript module architecture even if you aren't using Backbone.js. It utilizes the module pattern, application-level and module-level communication using the facade (sandbox) and mediator patterns. It abstracts away the utility libraries that you use (such as templating and DOM manipulation) so you can swap alternatives anytime you want. Managing objects and module communication One of the most important ways to keep the application code maintainable is to reduce the tight coupling between modules and objects. If you are following the module pattern, you should never let one module communicate with another directly. Loose coupling adds a level of restriction in your code, and a change in one module will never enforce a change in the rest of the application. Moreover, it lets you re-use the same modules elsewhere. But how can we communicate if there is no direct relationship? The two important patterns we use in this case are the observer and mediator patterns. Using the observer/PubSub pattern The PubSub pattern is nothing but the event dispatcher. It works as a messaging channel between the object (publisher) that fires the event and another object (subscriber) that receives the notification. We mentioned earlier that we can have an application-level event aggregator as a property of the Application object. This event aggregator can work as the common channel via which the other modules can communicate, and that too without interacting directly. Even at the module-level, you may need a common event dispatcher only for that module; the views, models, and collections of that module can use it to communicate with each other. However, publishing too many events via a dispatcher sometimes makes it difficult to manage them and you must be careful enough to understand which events you should publish via a generic dispatcher and which ones you should fire on a certain component only. Anyhow, this pattern is one of the best tools to design a decoupled system, and you should always have one ready for use in your module-based application. Summary This article dealt with one of the most important topics of Backbone.js-based application development. At the framework level, learning Backbone is quite easy and developers get a complete grasp over it in a very short period of time. Resources for Article: Further resources on this subject: Building an app using Backbone.js [article] Testing Backbone.js Application [article] Understanding Backbone [article]
Read more
  • 0
  • 0
  • 8321

article-image-research-techniques
Packt
21 Jan 2014
10 min read
Save for later

Research Techniques

Packt
21 Jan 2014
10 min read
(For more resources related to this topic, see here.) The design process lays out what type of information or level of detail we should be seeking at a particular point in the project. It does not explain how to get the information we need. For this, we rely on various techniques. These are exercises or methodologies that help us ask the appropriate questions and then analyze the answers we receive. These techniques will help us obtain the information we require to ensure our design solutions are on target and offer value to the end user. I have demonstrated the use of a few of these techniques in the example projects included in this article. However, since each project will require a slightly different approach, and because there are so many options available, it would be impractical to find an example that would adequately illustrate them all. There has been much written about these methodologies that is worth researching further. An experienced UX designer will know most of these and many other techniques, and should know when it is appropriate to employ them. Commonly used, effective research techniques Here is a very brief description of several methodologies aimed at helping us get the answers we seek during the research phase of a project. There are many others, and there will be many more developed as the software design industry continues to mature. I would recommend searching the Internet or other related books for more implementation details and examples of their usage. Stakeholder interviews Getting the project details from the primary stakeholders is likely the first thing we will need to do to get started on any project. The list of potential questions can be quite long. However, they usually roll up under one of the following primary questions: Who is going to use this software or site? What tasks does the user wish to accomplish? What does the maker of the software or site wish to accomplish? What technology will be used? (Are there any limitations to consider?) Why would the public use your software or site over another? What content will be needed to support the user in accomplishing their goals? If we are redesigning an existing site or application, we will likely find it valuable to seek answers to these additional questions: What features or complexities are hampering or otherwise negatively affecting the existing user experience? What additional features would the user or publisher find helpful in the next version of the product? Design tenet scorecard Design tenets are a list of the primary design attributes or qualities that are valued by the company or client we are working with. These attributes can describe the quality of interaction, visual style, tone of the text-based content, or even qualities that are a bit more technical in nature. Simply put, they can be anything that we would like to see represented in every interface we create. Here is an example scorecard: When there is misalignment on the vision or execution of a product or interface, it can be extremely helpful to put these tenets in the form of a scorecard. We then use this to grade the interface we have created against each design tenet. More often than not, one or more of the design tenets will have been neglected or entirely absent from the interface. Including this examination in our design reviews can help turn a general sense of dissatisfaction with a particular design solution into a focused discussion about specific attributes that need to be improved. This example scorecard is one that I recently created and used with a client. I managed to get everyone involved with the product development in the same room to quickly brainstorm what the company's design values were. Together, we defined seven design tenets or attributes that were desired in every interface we created. The idea being that if each of these values were adequately represented, we would have a higher likelihood of obtaining the company's goals. We would have a higher likelihood of producing a product that successfully gave the customer what they needed. I realize that this might seem to be of little value. After all, the tenets we have listed are all things that we should be striving for all of the time. However, each company will have a unique set of design attributes that they value above all others. There's a very good chance that they will not match our own personal values. So, it is important to understand what they are from the start so we can deliver a solution that matches their expectations. If we don't understand their values, we will design with our own values in mind. That doesn't always satisfy the client. Understanding the client's values may also help us understand where we need to educate them regarding the possible negative effects their particular values could have on the experience. For instance, let's say our client says they really appreciate new cutting edge interfaces. They like inventing new ways of solving problems with their software. They also say that they like clean interfaces that are not bogged down with a lot of help content or explanations. In this scenario, we can point to a potential conflict that might arise with this combination of values. We can explain that without some sort of tutorial content for this new interface, we may find we have a lot of users who just don't understand how the product is intended to work. The example scorecard I have included here offered significant value during the wireframing process of the project I was working on. The project started out fine, but I started to receive requests from one team member who thought the interface should be less guided and much more freeform. His desire for less navigation and guidance conflicted with the previously documented design tenet that stated that the product should include an "obvious task flow". Utilizing the scorecard, I was able to pinpoint where his requests were conflicting with the design attributes established by the team. It helped explain the logic of the design decisions I had made. And, it put the onus on him to justify his request with the knowledge that it was out of alignment with the team's prescribed values. In the end, it saved us a lot of time and effort. We were better able to focus on attributes of value and avoid going in directions that ran counter to those values. Competitive analysis Examining similar applications, sites, or products is a reliable way to quickly determine how much work is needed to compete in the existing marketplace. This exercise entails crawling through each product to examine and document the following: Product features of value Each product's target market What they do right and where they fail New ideas and features that will help offer a better experience Creating a summary of this research will help us create a plan to meet or exceed the competition. Reviewing the results of this research with the team and following up the review with a brainstorming session is a very effective way to kick-start some new ideas. Though our ultimate plan is to create something new that completely revolutionizes the marketplace, we often have to start by getting a simple v1 product into the marketplace. This is commonly referred to as the MVP or Minimum Viable Product. This means the product contains only those features that are essential for it to function in its most basic form. It can be easy to get caught up in the fervor to design something that beats out the competition with our initial release. There are times when this can be done. However, it is often smarter to promote a feature roadmap that plans out the evolution of our product through multiple versioned releases. As designers, we will likely need to help define how the experience will evolve through these multiple releases. We'll want to ensure that features are released in an order that will make sense to the user, and will always maintain the usability and integrity of the product. Personas and user profiles Personas are invented avatars that represent a certain segment of our end users. Using personas during the design process is a very common means of gaining an understanding of what typical customers or users look like. They do an amazing job of helping the team focus their efforts on what a particular user might need. Without them, it's easy to unknowingly have the team examine the interface from the point of view of different users. This can cause disagreement regarding what a particular interface needs to include to appropriately serve its end user. This is an easy trap to fall into. Several years ago, I found myself in this situation. I was presenting some new product designs with a co-worker. The product was addressing some very complex task flows that were not easy for a novice user to understand. A disagreement sprung up about how we were handling some of the details in the experience. After a couple of hours going back and forth about why the interface succeeded or failed, we finally figured out that we were thinking of two entirely different users. My teammate was looking at the designs through the eyes of an admin or expert user. I was attempting to design with the inexperienced user in mind. Once I understood the point of view through which he was examining the interface, I was able to adequately address his concerns by showing him the admin task flow we had previously created. The user he had in mind was actually never going to see the interface we had been reviewing. This was a costly misunderstanding that caused frustration and wasted a lot of time. Had we been using our persona's names during our conversation, it would've become obvious that we were thinking about two entirely different user profiles. Creating personas The process of creating personas starts with researching what types of users are expected to use the application or site you are creating. A quick brainstorming session with the team should be enough to get a list and description of these user types. As we examine the potential users in our list, it's common to find that we have many user types that are very similar. We'll want to consolidate those down to a number that is easy to remember by creating a representative for multiple user types. Here's an example of what this might look like. As we can see from the following example, our list of potential users is too long to be useful. 18 different user types are far too many to remember. We really need to narrow this down to something more manageable. I can't really give an ideal number of personas to develop. It will depend largely on the product. However, I would say it is common to have somewhere between three to six different personas. Summary In this article, we have covered basic concepts of research techniques that help us to obtain the information which is required to design applications and offer valuable services to the end users. Resources for Article: Further resources on this subject: Axure RP 6 Prototyping Essentials: Advanced Interactions [Article] Organizing your Balsamiq files [Article] Ten IPython essentials [Article]
Read more
  • 0
  • 0
  • 1381

article-image-article-dart-server-with-dartling-and-mongodb
Packt
21 Jan 2014
10 min read
Save for later

Dart Server with Dartling and MongoDB

Packt
21 Jan 2014
10 min read
(For more resources related to this topic, see here.) Server Side Dart Creating a server in Dart is surprisingly simple, once the asynchronous programming with Futures is understood. Starting a server To start a server run the main function in todo_mongodb/todo_server_dartling_mongodb/bin/server.dart. void main() { db = new TodoDb(); db.open().then((_) { start(); }); } An access to a MongoDB database is prepared in the TodoDb constructor in todo_mongodb/todo_server_dartling_mongodb/lib/persistence/mongodb.dart. The database is opened, then the server is started. start() { HttpServer.bind(HOST, PORT) .then((server) { server.listen((HttpRequest request) { switch (request.method) { case "GET": handleGet(request); break; case 'POST': handlePost(request); break; case 'OPTIONS': handleOptions(request); break; default: defaultHandler(request); } }); }) .catchError(print) .whenComplete(() => print('Server at http://$HOST:$PORT')); } If there are no problems, the following message is displayed in the console of Dart Editor. Server at http://127.0.0.1:8080 The server accepts either GET or POST requests. void handleGet(HttpRequest request) { HttpResponse res = request.response; print('${request.method}: ${request.uri.path}'); addCorsHeaders(res); res.headers.contentType = new ContentType("application", "json", charset: 'utf-8'); List<Map> jsonList = db.tasks.toJson(); String jsonString = convert.JSON.encode(jsonList); print('JSON list in GET: ${jsonList}'); res.write(jsonString); res.close(); } The server, through a GET request, sends to a client CORS headers to allow a browser to send requests to different servers. void handlePost(HttpRequest request) { print('${request.method}: ${request.uri.path}'); request.listen((List<int> buffer) { var jsonString = new String.fromCharCodes(buffer); List<Map> jsonList = convert.JSON.decode(jsonString); print('JSON list in POST: ${jsonList}'); _integrateDataFromClient(jsonList); }, onError: print); } The POST request integrates data from a client to the model. _integrateDataFromClient(List<Map> jsonList) { var clientTasks = new Tasks.fromJson(db.tasks.concept, jsonList); var serverTaskList = db.tasks.toList(); for (var serverTask in serverTaskList) { var clientTask = clientTasks.singleWhereAttributeId('title', serverTask.title); if (clientTask == null) { new RemoveAction(db.session, db.tasks, serverTask).doit(); } } for (var clientTask in clientTasks) { var serverTask = db.tasks.singleWhereAttributeId('title', clientTask.title); if (serverTask != null) { if (serverTask.updated.millisecondsSinceEpoch < clientTask.updated.millisecondsSinceEpoch) { new SetAttributeAction( db.session, serverTask, 'completed', clientTask.completed).doit(); } } else { new AddAction(db.session, db.tasks, clientTask).doit(); } } } MongoDB database MongoDB is used to load all data from the database into the model of Dartling. In general, there may be more than one domain in a repository of Dartling. Also, there may be more than one model in a domain. A model has concepts with attributes and relationships between concepts. The TodoMVC model has only one concept - Task and no relationships. A model in Dartling may also be considered as an in-memory graphical database. It has actions, action pre and post validations, error handling, select data views, view update propagations, reaction events, transactions, sessions with the trans(action) past, so that undos and redos on the model may be done. You can add, remove, update, validate, find, select and order data. Actions or transactions may be used to support unrestricted undos and redos in a domain session. A transaction is an action that contains other actions. The domain allows any object to react to actions in its models. The empty Dartling model is prepared in the TodoDb constructor. TodoDb() { var repo = new TodoRepo(); domain = repo.getDomainModels('Todo'); domain.startActionReaction(this); session = domain.newSession(); model = domain.getModelEntries('Mvc'); tasks = model.tasks; } It is in the open method that the data are loaded into the model. Future open() { Completer completer = new Completer(); db = new Db('${DEFAULT_URI}${DB_NAME}'); db.open().then((_) { taskCollection = new TaskCollection(this); taskCollection.load().then((_) { completer.complete(); }); }).catchError(print); return completer.future; } In the MongoDB database there is one collection of tasks, where each task is a JSON document. This collection is defined in the TaskCollection class in mongodb.dart. The load method in this class transfers tasks from the database to the model. Future load() { Completer completer = new Completer(); dbTasks.find().toList().then((taskList) { taskList.forEach((taskMap) { var task = new Task.fromDb(todo.tasks.concept, taskMap); todo.tasks.add(task); }); completer.complete(); }).catchError(print); return completer.future; } There is only one concept in the model. Thus, the concept is entry and its entities are tasks (of the Tasks class). After the data are loaded, only the tasks entities may be used. The TodoDb class implements ActionReactionApi of Dartling. A reaction to an action in the model is defined in the react method of the TodoDb class. react(ActionApi action) { if (action is AddAction) { taskCollection.insert(action.entity); } else if (action is RemoveAction) { taskCollection.delete(action.entity); } else if (action is SetAttributeAction) { taskCollection.update(action.entity); } } } Tasks are inserted, deleted and updated in the mongoDB database in the following methods of the TaskCollection class. Future<Task> insert(Task task) { var completer = new Completer(); var taskMap = task.toDb(); dbTasks.insert(taskMap).then((_) { print('inserted task: ${task.title}'); completer.complete(); }).catchError(print); return completer.future; } Future<Task> delete(Task task) { var completer = new Completer(); var taskMap = task.toDb(); dbTasks.remove(taskMap).then((_) { print('removed task: ${task.title}'); completer.complete(); }).catchError(print); return completer.future; } Future<Task> update(Task task) { var completer = new Completer(); var taskMap = task.toDb(); dbTasks.update({"title": taskMap['title']}, taskMap).then((_) { print('updated task: ${task.title}'); completer.complete(); }).catchError(print); return completer.future; } } Dartling tasks The TodoMVC model is designed in Model Concepts. The graphical model is transformed into a JSON document. { "width":990, "height":580, "boxes":[ { "name":"Task", "entry":true, "x":85, "y":67, "width":80, "height":80, "items":[ { "sequence":10, "name":"title", "category":"identifier", "type":"String", "init":"", "essential":true, "sensitive":false }, { "sequence":20, "name":"completed", "category":"required", "type":"bool", "init":"false", "essential":true, "sensitive":false }, { "sequence":30, "name":"updated", "category":"required", "type":"DateTime", "init":"now", "essential":false, "sensitive":false } ] } ], "lines":[ ] } This JSON document is used in dartling_gen to generate the model in Dart. The lib/gen and lib/todo folders contain the generated model. The gen folder contains the generic code that should not be changed by a programmer. The todo folder contains the specific code that may be changed by a programmer. The specific code has Task and Tasks classes that are augmented by some specific code. class Task extends TaskGen { Task(Concept concept) : super(concept); Task.withId(Concept concept, String title) : super.withId(concept, title); // begin: added by hand Task.fromDb(Concept concept, Map value): super(concept) { title = value['title']; completed = value['completed']; updated = value['updated']; } Task.fromJson(Concept concept, Map value): super(concept) { title = value['title']; completed = value['completed'] == 'true' ? true : false; updated = DateTime.parse(value['updated']); } bool get left => !completed; bool get generate => title.contains('generate') ? true : false; Map toDb() { return { 'title': title, 'completed': completed, 'updated': updated }; } bool preSetAttribute(String name, Object value) { bool validation = super.preSetAttribute(name, value); if (name == 'title') { String title = value; if (validation) { validation = title.trim() != ''; if (!validation) { var error = new ValidationError('pre'); error.message = 'The title should not be empty.'; errors.add(error); } } if (validation) { validation = title.length <= 64; if (!validation) { var error = new ValidationError('pre'); error.message = 'The "${title}" title should not be longer than 64 characters.'; errors.add(error); } } } return validation; } // end: added by hand } class Tasks extends TasksGen { Tasks(Concept concept) : super(concept); // begin: added by hand Tasks.fromJson(Concept concept, List<Map> jsonList): super(concept) { for (var taskMap in jsonList) { add(new Task.fromJson(concept, taskMap)); } } Tasks get completed => selectWhere((task) => task.completed); Tasks get left => selectWhere((task) => task.left); Task findByTitleId(String title) { return singleWhereId(new Id(concept)..setAttribute('title', title)); } // end: added by hand } Client Side Dart The Todo web application may be run in the Dartium virtual machine within the Dart Editor, or as a JavaScript application run in any modern browser (todo_mongodb/todo_client_idb/web/app.html). The client application has both the model in todo_mongodb/todo_client_idb/lib/model and the view of the model in todo_mongodb/todo_client_idb/lib/view. The model has two Dart files, idb.dart for IndexedDB and model.dart for plain objects created from scratch without any model framework such as Dartling. The view is done in DOM. The application delegates the use of a local storage to the IndexedDB. A user of the application communicates with the Dart server by two buttons. The To server button sends local data to the server, while the From server button brings changes to the local data from the MongoDB database. ButtonElement toServer = querySelector('#to-server'); toServer.onClick.listen((MouseEvent e) { var request = new HttpRequest(); request.onReadyStateChange.listen((_) { if (request.readyState == HttpRequest.DONE && request.status == 200) { serverResponse = 'Server: ' + request.responseText; } else if (request.readyState == HttpRequest.DONE && request.status == 0) { // Status is 0...most likely the server isn't running. serverResponse = 'No server'; } }); var url = 'http://127.0.0.1:8080'; request.open('POST', url); request.send(_tasksStore.tasks.toJsonString()); }); ButtonElement fromServer = querySelector('#from-server'); fromServer.onClick.listen((MouseEvent e) { var request = new HttpRequest(); request.onReadyStateChange.listen((_) { if (request.readyState == HttpRequest.DONE && request.status == 200) { String jsonString = request.responseText; serverResponse = 'Server: ' + request.responseText; if (jsonString != '') { List<Map> jsonList = JSON.decode(jsonString); print('JSON list from the server: ${jsonList}'); _tasksStore.loadDataFromServer(jsonList) .then((_) { var tasks = _tasksStore.tasks; _clearElements(); loadElements(tasks); }) .catchError((e) { print('error in loading data into IndexedDB from JSON list'); }); } } else if (request.readyState == HttpRequest.DONE && request.status == 0) { // Status is 0...most likely the server isn't running. serverResponse = 'No server'; } }); var url = 'http://127.0.0.1:8080'; request.open('GET', url); request.send('update-me'); });> Server data are loaded in the loadDataFromServer method of the TasksStore class in todo_mongodb/todo_client_idb/lib/model/idb.dart. Future loadDataFromServer(List<Map> jsonList) { Completer completer = new Completer(); Tasks integratedTasks = _integrateDataFromServer(jsonList); clear() .then((_) { int count = 0; for (Task task in integratedTasks) { addTask(task) .then((_) { if (++count == integratedTasks.length) { completer.complete(); } }); } }); return completer.future; } The server data are integrated into the local data by the _integrateDataFromServer method of the TasksStore class. Tasks _integrateDataFromServer(List<Map> jsonList) { var serverTasks = new Tasks.fromJson(jsonList); var clientTasks = tasks.copy(); var clientTaskList = clientTasks.toList(); for (var clientTask in clientTaskList) { if (!serverTasks.contains(clientTask.title)) { clientTasks.remove(clientTask); } } for (var serverTask in serverTasks) { if (clientTasks.contains(serverTask.title)) { var clientTask = clientTasks.find(serverTask.title); clientTask.completed = serverTask.completed; clientTask.updated = serverTask.updated; } else { clientTasks.add(serverTask); } } return clientTasks; } Summary The TodoMVC client-server application is developed in Dart. The web application is done in DOM with local data from a simple model stored in an IndexedDB database. The local data are sent to the server as a JSON document. Data from the server are received also as a JSON document. Both on a client and on the server, data are integrated in the model. The server uses the Dartling domain framework for its model. The model is stored in the MongoDB database. The action events from Dartling are used to propagate changes from the model to the database. Resources for Article: Further resources on this subject: HTML5: Generic Containers [article] HTML5: Getting Started with Paths and Text [article] HTML5 Presentations - creating our initial presentation [article]
Read more
  • 0
  • 0
  • 5472

article-image-exploring-advanced-interactions-webdriver
Packt
21 Jan 2014
9 min read
Save for later

Exploring Advanced Interactions of WebDriver

Packt
21 Jan 2014
9 min read
(For more resources related to this topic, see here.) Understanding actions, build, and perform We know how to take some basic actions, such as clicking on a button and typing text into a textbox; however, there are many scenarios where we have to perform multiple actions at the same time. For example, keeping the Shift button pressed and typing text for uppercase letters, and the dragging and dropping mouse actions. Let's see a simple scenario here. Open the selectable.html file that is attached with this book. You will see tiles of numbers from 1 to 12. If you inspect the elements with Firebug, you will see an ordered list tag (<ol>) and 12 list items (<li>) under it, as shown in the following code: <ol id="selectable" class="ui-selectable"> <li class="ui-state-default ui-selectee" name="one">1</li> <li class="ui-state-default ui-selectee" name="two">2</li> <li class="ui-state-default ui-selectee" name="three">3</li> <li class="ui-state-default ui-selectee" name="four">4</li> <li class="ui-state-default ui-selectee" name="five">5</li> <li class="ui-state-default ui-selectee" name="six">6</li> <li class="ui-state-default ui-selectee" name="seven">7</li> <li class="ui-state-default ui-selectee" name="eight">8</li> <li class="ui-state-default ui-selectee" name="nine">9</li> <li class="ui-state-default ui-selectee" name="ten">10</li> <li class="ui-state-default ui-selectee" name="eleven">11</li> <li class="ui-state-default ui-selectee" name="twelve">12</li> </ol> If you click a number, it's background color changes to orange. Try selecting the 1, 3, and 5 numbered tiles. You do that by holding the Ctrl key + 1 numbered tile + 3 numbered tile + 5 numbered tile. So, this involves performing multiple actions, that is, holding the Ctrl key continuously and clicking on 1, 3, and 5 tiles. How do we perform these multiple actions using WebDriver? The following code demonstrates that: public class ActionBuildPerform {     public static void main(String... args) {       WebDriver driver = new FirefoxDriver();       driver.get("file://C:/selectable.html");       WebElement one = driver.findElement(By.name("one"));       WebElement three = driver.findElement(By.name("three"));      WebElement five = driver.findElement(By.name("five"));       // Add all the actions into the Actions builder.      Actions builder = new Actions(driver);         builder.keyDown( Keys.CONTROL )               .click(one)              .click(three)              .click(five)              .keyUp(Keys.CONTROL);        // Generate the composite action.        Action compositeAction = builder.build();        // Perform the composite action.        compositeAction.perform( );       }    } Now, if you see the code, line number 9 is where we are getting introduced to a new class named Actions. This Actions class is the one that is used to emulate all the complex user events. Using this, the developer of the test script could combine all the necessary user gestures into one composite action. From line 9 to line 14, we have declared all the actions that are to be executed to achieve the functionality of clicking on the numbers 1, 3, and 5. Once all the actions are grouped together, we build that into a composite action. This is contained on line 16. Action is an interface that has only the perform() method, which executes the composite action. Line 18 is where we are actually executing the action using the perform() method. So, to make WebDriver perform multiple actions at the same time, you need to follow a three-step process of using the user-facing API of the Actions class to group all the actions, then build the composite action, and then the perform the action. This process can be made into a two-step process as the perform() method internally calls the build() method. So the previous code will look as follows: public class ActionBuildPerform {     public static void main(String... args) {       WebDriver driver = new FirefoxDriver();       driver.get("file://C:/selectable.html");       WebElement one = driver.findElement(By.name("one"));       WebElement three = driver.findElement(By.name("three"));      WebElement five = driver.findElement(By.name("five"));       // Add all the actions into the Actions builder.     Actions builder = new Actions(driver);         builder.keyDown( Keys.CONTROL )               .click(one)              .click(three)              .click(five)              .keyUp(Keys.CONTROL);        // Perform the action.        builder.perform( );   } } In the preceding code, we have directly invoked the perform() method on the Actions instance, which internally calls the build() method to create a composite action before executing it. In the subsequent sections of this article, we will take a closer look at the Actions class. All the actions are basically divided into two categories: mouse-based actions and keyboard-based actions. In the following sections, we will discuss all the actions that are specific to the mouse and keyboard available in the Actions class. Learning mouse-based interactions There are around eight different mouse actions that can be performed using the Actions class. We will see each of their syntax and a working example. The moveByOffset action The moveByOffset method is used to move the mouse from its current position to another point on the web page. Developers can specify the X distance and Y distance the mouse has to be moved. When the page is loaded, generally the initial position of a mouse would be (0, 0), unless there is an explicit focus declared by the page. The API syntax for the moveByOffset method is as follows: public Actions moveByOffset(int xOffSet, int yOffSet) In the preceding code, xOffSet is the input parameter providing the WebDriver the amount of offset to be moved along the x axis. A positive value is used to move the cursor to the right, and a negative value is used to move the cursor to the left. yOffSet is the input parameter providing the WebDriver the amount of offset to be moved along the y axis. A positive value is used to move the cursor down along the y axis and a negative value is used to move the cursor toward the top. When the xOffSet and yOffSet values result in moving the cursor out of the document, a MoveTargetOutOfBoundsException is raised. Let's see a working example of it. The objective of the following code is to move the cursor on to the number 3 tile on the web page:  public class MoveByOffSet{   public static void main(String... args) {     WebDriver driver = new FirefoxDriver();     driver.get("file://C:/Selectable.html");     WebElement three = driver.findElement(By.name("three"));     System.out.println("X coordinate: "+three.getLocation().getX()+" Y coordinate: "+three.getLocation().getY());     Actions builder = new Actions(driver);     builder.moveByOffset(three.getLocation().getX()+1, three.getLocation().getY()+1);     builder.perform();   }  } We have added +1 to the coordinates, because if you observe the element in Firebug, we have a style border of 1 px. Border is a CSS-style attribute, which when applied to an element, will add a border of the specified color around the element with the specified amount of thickness. Though the previous code does move your mouse over tile 3, we don't realize it because we are not doing any action there. We will see that when we use this moveByOffset() method in combination with the click method shortly. The moveByOffset() method may not work in Mac OSX and may raise a JavaScript error when used independently like the previous code. The click at current location action The click method is used to simulate the left-click of your mouse at its current point of location. This method doesn't really realize where or on which element it is clicking. It just blindly clicks wherever it is at that point of time. Hence, this method is used in combination with some other action rather than independently, to create a composite action. The API syntax for the click method is as follows: public Actions click() The click method doesn't really have any context about where it is performing its action; hence, it doesn't take any input parameter. Let's see a code example of the click method: public class MoveByOffsetAndClick{   public static void main(String... args) {     WebDriver driver = new FirefoxDriver();     driver.get("file://C:/Selectable.html");     WebElement seven = driver.findElement(By.name("seven"));     System.out.println("X coordinate: "+seven.getLocation().getX()+" Y coordinate: "+seven.getLocation().getY());     Actions builder = new Actions(driver);     builder.moveByOffset( seven.getLocation ().getX()+1, seven.getLocation().getY()+1).click();     builder.perform();   } } Line 8 is where we have used a combination of the moveByOffset() and click() methods to move the cursor from point (0, 0) to the point of tile 7. Because the initial position of the mouse is (0, 0), the X, Y offset provided for the moveByOffset() method is nothing but the location of the tile 7 element. Now, lets try to move the cursor from tile 1 to tile 11 and from there to tile 5 and see how the code looks. Before we get into the code, let's inspect the selectable.html page using Firebug. The following is the style of each tile: #selectable li {     float: left;     font-size: 4em;     height : 80px;     text-align: center;     width : 100px; } .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default {     background: url("images/ui-bg_glass_75_e6e6e6_1x400.png") repeat-x scroll 50% 50% #E6E6E6;     border : 1px solid #D3D3D3;     color: #555555;     font-weight: normal; } The three elements with which we are concerned for our offset movement in the preceding style code are: height, width, and the border thickness. Here, the height value is 80px, width value is 100px, and border value is 1px. Use these three factors to calculate the offset to navigate from one tile to the other. Note that the border thickness between any two tiles will result in 2 px; that is, 1 px from each tile. The following is the code that uses the moveByOffset and click() methods to navigate from tile 1 to tile 11, and from there to tile 5: public class MoveByOffsetAndClick{   public static void main(String... args) {     WebDriver driver = new FirefoxDriver();     driver.get("file://C:/Selectable.html");     WebElement one = driver.findElement(By.name("one"));     WebElement eleven = driver.findElement(By.name("eleven"));     WebElement five = driver.findElement(By.name("five"));     int border = 1;     int tileWidth = 100;     int tileHeight = 80;     Actions builder = new Actions(driver);     //Click on One     builder.moveByOffset( one.getLocation ().getX()+border, one.getLocation().getY()+border).click();     builder.build().perform();     // Click on Eleven     builder.moveByOffset( 2*tileWidth+4*border, 2*tileHeight+4*border).click();     builder.build().perform();    //Click on Five     builder.moveByOffset( -2*tileWidth-4*border, -tileHeight-2*border).click();     builder.build().perform();    }  }
Read more
  • 0
  • 0
  • 2194

article-image-fundamentals
Packt
20 Jan 2014
4 min read
Save for later

Fundamentals

Packt
20 Jan 2014
4 min read
(For more resources related to this topic, see here.) Vulnerability Assessment and Penetration Testing Vulnerability Assessment ( VA) and Penetrating Testing ( PT or PenTest ) are the most common types of technical security risk assessments or technical audits conducted using different tools. These tools provide best outcomes if they are used optimally. An improper configuration may lead to multiple false positives that may or may not reflect true vulnerabilities. Vulnerability assessment tools are widely used by all, from small organizations to large enterprises, to assess their security status. This helps them with making timely decisions to protect themselves from these vulnerabilities. Vulnerability Assessments and PenTests using Nessus. Nessus is a widely recognized tool for such purposes. This section introduces you to basic terminology with reference to these two types of assessments. Vulnerability in terms of IT systems can be defined as potential weaknesses in system/infrastructure that, if exploited, can result in the realization of an attack on the system. An example of a vulnerability is a weak, dictionary-word password in a system that can be exploited by a brute force attack (dictionary attack) attempting to guess the password. This may result in the password being compromised and an unauthorized person gaining access to the system. Vulnerability Assessment is a phase-wise approach to identifying the vulnerabilities existing in an infrastructure. This can be done using automated scanning tools such as Nessus, which uses its set of plugins corresponding to different types of known security loopholes in infrastructure, or a manual checklist-based approach that uses best practices and published vulnerabilities on well-known vulnerability tracking sites. The manual approach is not as comprehensive as a tool-based approach and will be more time-consuming. The kind of checks that are performed by a vulnerability assessment tool can also be done manually, but this will take a lot more time than an automated tool. Penetration Testing has an additional step for vulnerability assessment, exploiting the vulnerabilities. Penetration Testing is an intrusive test, where the personnel doing the penetration test will first do a vulnerability assessment to identify the vulnerabilities, and as a next step, will try to penetrate the system by exploiting the identified vulnerabilities. Need for Vulnerability Assessment It is very important for you to understand why Vulnerability Assessment or Penetration Testing is required. Though there are multiple direct or indirect benefits for conducting a vulnerability assessment or a PenTest, a few of them have been recorded here for your understanding. Risk prevention Vulnerability Assessment uncovers the loopholes/gaps/vulnerabilities in the system. By running these scans on a periodic basis, an organization can identify known vulnerabilities in the IT infrastructure in time. Vulnerability Assessment reduces the likelihood of noncompliance to the different compliance and regulatory requirements since you know your vulnerabilities already. Awareness of such vulnerabilities in time can help an organization to fi x them and mitigate the risks involved in advance before they get exploited. The risks of getting a vulnerability exploited include: Financial loss due to vulnerability exploits Organization reputation Data theft Confidentiality compromise Integrity compromise Availability compromise Compliance requirements The well-known information security standards (for example, ISO 27001, PCI DSS, and PA DSS) have control requirements that mandate that a Vulnerability Assessment must be performed. A few countries have specific regulatory requirements for conducting Vulnerability Assessments in some specific industry sectors such as banking and telecom. The life cycles of Vulnerability Assessment and Penetration Testing This section describes the key phases in the life cycles of VA and PenTest. These life cycles are almost identical; Penetration Testing involves the additional step of exploiting the identified vulnerabilities. It is recommended that you perform testing based on the requirements and business objectives of testing in an organization, be it Vulnerability Assessment or Penetration Testing. The following stages are involved in this life cycle: Scoping Information gathering Vulnerability scanning False positive analysis Vulnerability exploitation (Penetration Testing) Report generation The following figure illustrates the different sequential stages recommended to follow for a Vulnerability Assessment or Penetration Testing: Summary In this article, we covered an introduction to Vulnerability Assessment and Penetration Testing, along with an introduction to Nessus as a tool and steps on installing and setting up Nessus. Resources for Article: Further resources on this subject: CISSP: Vulnerability and Penetration Testing for Access Control [Article] Penetration Testing and Setup [Article] Web app penetration testing in Kali [Article]
Read more
  • 0
  • 0
  • 14737

article-image-article-what_is_ngui
Packt
20 Jan 2014
8 min read
Save for later

What is NGUI?

Packt
20 Jan 2014
8 min read
(For more resources related to this topic, see here.) The Next-Gen User Interface kit is a plugin for Unity 3D. It has the great advantage of being easy to use, very powerful, and optimized compared to Unity's built-in GUI system, UnityGUI. Since it is written in C#, it is easily understandable and you may tweak it or add your own features, if necessary. The NGUI Standard License costs $95. With this, you will have useful example scenes included. I recommend this license to start comfortably—a free evaluation version is available, but it is limited, outdated, and not recommended. The NGUI Professional License, priced at $200, gives you access to NGUI's GIT repository to access the latest beta features and releases in advance. A $2000 Site License is available for an unlimited number of developers within the same studio. Let's have an overview of the main features of this plugin and see how they work. UnityGUI versus NGUI With Unity's GUI, you must create the entire UI in code by adding lines that display labels, textures, or any other UI element on the screen. These lines have to be written inside a special function, OnGUI(), that is called for every frame. This is no longer necessary; with NGUI, UI elements are simple GameObjects! You can create widgets—this is what NGUI calls labels, sprites, input fields, and so on—move them, rotate them, and change their dimensions using handles or the Inspector. Copying, pasting, creating prefabs, and every other useful feature of Unity's workflow is also available. These widgets are viewed by a camera and rendered on a layer that you can specify. Most of the parameters are accessible through Unity's Inspector, and you can see what your UI looks like directly in the Game window, without having to hit the Play button. Atlases Sprites and fonts are all contained in a large texture called atlas. With only a few clicks, you can easily create and edit your atlases. If you don't have any images to create your own UI assets, simple default atlases come with the plugin. That system means that for a complex UI window composed of different textures and fonts, the same material and texture will be used when rendering. This results in only one draw call for the entire window. This, along with other optimizations, makes NGUI the perfect tool to work on mobile platforms. Events NGUI also comes with an easy-to-use event framework that is written in C#. The plugin comes with a large number of additional components that you can attach to GameObjects. These components can perform advanced tasks depending on which events are triggered: hover, click, input, and so on. Therefore, you may enhance your UI experience while keeping it simple to configure. Code less, get more! Localization NGUI comes with its own localization system, enabling you to easily set up and change your UI's language with the push of a button. All your strings are located in the .txt files: one file per language. Shaders Lighting, normal mapping, and refraction shaders are supported in NGUI, which can give you beautiful results. Clipping is also a shader-controlled feature with NGUI, used for showing or hiding specific areas of your UI. We've now covered what NGUI's main features are, and how it can be useful to us as a plugin, and now it's time to import it inside Unity. Importing NGUI After buying the product from the Asset Store or getting the evaluation version, you have to download it. Perform the following steps to do so: Create a new Unity project. Navigate to Window | Asset Store. Select your downloads library. Click on the Download button next to NGUI: Next-Gen UI. When the download completes, click on the NGUI icon / product name in the library to access the product page. Click on the Import button and wait for a pop-up window to appear. Check the checkbox for NGUI v.3.0.2.unity package and click on Import. In the Project view, navigate to Assets | NGUI and double-click on NGUI v.3.0.2. A new imported pop-up window will appear. Click on Import again. Click any button on the toolbar to refresh it.The NGUI tray will appear! The NGUI tray will look like the following screenshot: You have now successfully imported NGUI to your project. Let's create your first 2D UI. Creating your UI We will now create our first 2D user interface with NGUI's UI Wizard. This wizard will add all the elements needed for NGUI to work. Before we continue, please save your scene as Menu.unity. UI Wizard Create your UI by opening the UI Wizard by navigating to NGUI | Open | UIWizard from the toolbar. Let's now take a look at the UI Wizard window and its parameters. Window You should now have the following pop-up window with two parameters: Parameters The two parameters are as follows: Layer: This is the layer on which your UI will be displayed Camera: This will decide if the UI will have a camera, and its drop-down options are as follows: None: No camera will be created Simple 2D:Uses a camera with orthographic projection Advanced 3D:Uses a camera with perspective projection Separate UI Layer I recommend that you separate your UI from other usual layers. We should do it as shown in the following steps: Click on the drop-down menu next to the Layer parameter. Select Add Layer. Create a new layer and name it GUI2D. Go back to the UI Wizard window and select this new GUI2D layer for your UI. You can now click on the Create Your UI button. Your first 2D UI has been created! Your UI structure The wizard has created four new GameObjects on the scene for us: UI Root (2D) Camera Anchor Panel Let's now review each in detail. UI Root (2D) The UIRoot component scales widgets down to keep them at a manageable size. It is also responsible for the Scaling Style—it will either scale UI elements to remain pixel perfect or to occupy the same percentage of the screen, depending on the parameters you specify. Select the UI Root (2D) GameObject in the Hierarchy. It has the UIRoot.cs script attached to it. This script adjusts the scale of the GameObject it's attached to in order to let you specify widget coordinates in pixels, instead of Unity units as shown in the following screenshot: Parameters The UIRoot component has four parameters: Scaling Style: The following are the available scaling styles: PixelPerfect:This will ensure that your UI will always try to remain at the same size in pixels, no matter what resolution. In this scaling mode, a 300 x 200 window will be huge on a 320 x 240 screen and tiny on a 1920 x 1080 screen. That also means that if you have a smaller resolution than your UI, it will be cropped. FixedSize:This will ensure that your UI will be proportionally resized depending on the screen's height. The result is that your UI will not be pixel perfect but will scale to fit the current screen size. FixedSizeOnMobiles:This will ensure fixed size on mobiles and pixel perfect everywhere else. Manual Height: With the FixedSize scaling style, the scale will be based on this height. If your screen's height goes over or under this value, it will be resized to be displayed identically while maintaining the aspect ratio(width/height proportional relationship). Minimum Height: With the PixelPerfect scaling style, this parameter defines the minimum height for the screen. If your screen height goes below this value, your UI will resize. It will be as if the Scaling Style parameter was set to FixedSize with Manual Height set to this value. Maximum Height: With the PixelPerfect scaling style, this parameter defines the maximum height for the screen. If your screen height goes over this value,your UI will resize. It will be as if the ScalingStyle parameter was set to FixedSize with Manual Height set to this value. Please set the Scaling Style parameter to FixedSize with a Manual Height value of 1080. This will allow us to have the same UI on any screen size up to 1920 x 1080. Even though the UI will look the same on different resolutions, the aspect ratio is still a problem since the rescale is based on the screen's height only. If you want to cover both 4:3 and 16:9 screens, your UI should not be too large—try to keep it square.Otherwise, your UI might be cropped on certain screen resolutions. On the other hand, if you want a 16:9 UI, I recommend you force this aspect ratio only. Let's do it now for this project by performing the following steps: Navigate to Edit| Project Settings | Player. In the Inspectoroption, unfold the Resolution and Presentationgroup. Unfold the Supported Aspect Ratios group. Check only the 16:9 box. Summary In this article, we discussed NGUI's basic workflow—it works with GameObjects, uses atlases to combine multiple textures in one large texture, has an event system, can use shaders, and has a localization system. After importing the NGUI plugin, we created our first 2D UI with the UI Wizard, reviewed its parameters, and created our own GUI 2D layer for our UI to reside on. Resources for Article: Further resources on this subject: Unity 3D Game Development: Don't Be a Clock Blocker [Article] Component-based approach of Unity [Article] Unity 3: Building a Rocket Launcher [Article]
Read more
  • 0
  • 0
  • 11613
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at $19.99/month. Cancel anytime
article-image-server-logs
Packt
20 Jan 2014
9 min read
Save for later

Server Logs

Packt
20 Jan 2014
9 min read
(For more resources related to this topic, see here.) Monitoring a live system is crucial to maintaining stability and performance; not only to avoid potential failures but even for debugging and tracing back an event. That is why having a system record its activities results in a rich database of logs that can be used for investigation. Logfiles tell a fascinating story to those who can read it. They carry the history of all events narrated in thorough detail. ArcGIS for Server, like any other system, keeps logfiles for all events, from the basic "connection established" event to the severe "service failed to initiate" event. Logging levels Recording events on Server is done at different levels. You can tell Server to log every single event as it happens or filter to record only fatal errors. Consequently, recording fine events generates more logs than recording only those messages with errors. There are seven logging levels, and these are described in the following Esri table: Log level Description Severe This level logs serious problems that require immediate attention. It only includes severe messages. Warning This level logs moderate problems that require attention. It also includes severe-level messages. Info This level logs common administrative messages from Server, including messages about service creation and startup. It also includes severe and warning messages. Fine This level logs common messages from users of Server, such as names of operation requests received. It includes severe, warning, and info messages. Verbose This level logs messages providing more details about how Server completes an operation, such as whether each layer in a map service was drawn successfully, how fast the layer was drawn, and how long it took Server to access the layer's source data. This level includes severe, warning, info, and fine messages. Debug This level logs highly verbose messages designed for developers and support technicians who want to obtain a better understanding of the state of Server when troubleshooting. This level should not be used in a production environment as it may cause a significant decrease in Server performance. Off At this level, logging is turned off. Events are not logged with Server. As you can see, Debug is the finest level and keeps Server busy with logging events, making other important tasks suffer. Log analysis Logs can be viewed and refreshed actively from the ArcGIS for Server Manager window as they are written. To see your current logfiles, go to Manager and activate the Logs tab: Naturally, each GIS server generates its own logs and this is all saved by default at C:arcgisserverlogs. You cannot use a shared folder for this; each GIS server should generate its own logs in its directory, ArcGIS for Server aggregates those logs into the Server site, in a table view with filters options, which allows you to search through the logs. From the View Log Messages panel, click on Query to view the current logfiles as shown in the following screenshot. You might get messages different from mine. You might not have any messages if your current log level is set to only record errors, and there are no errors. To change the log level, click on Settings. From the Log Settings form, select Verbose from the Log Level drop-down list. You can set the logs to be cleared automatically if you want to. Keep the rest of the settings intact and click on the Save button. By default, the logs are kept on the GIS server for three months. If you are planning to keep the logs for longer than that, perhaps for offline analysis, you may want to archive them periodically and delete them. Generally, clearing the logs is better for performance. This will be discussed in the coming pages. Best practice Since logs are saved to disk frequently, they use high IO. It is recommended that you point the log path to a local directory, preferably on a Solid State Drive (SSD) for best performance. Now, let us see how the logs are being generated. First of all, let us clear all the logs to start afresh. To do that, click on Delete Logs from ArcGIS for Server Manager and then click on Yes, as shown in the following screenshot: Now that the logs are cleared, we will activate the parcels service by simply visiting the REST URL and then checking the log. Type the REST URL on a new browser page and press Enter. You should see something like the following screenshot if you have access to the service: Go back to your logs and click on Query to refresh the page. You should see one message in the table. You might see other messages from Server that happened to be executed at that particular time but look for this one: Level Time Message Source Machine User Name INFO Nov 17, 2013, 11:18:26 AM Request user: Anonymous user, Service: Parcels/MapServer Rest GIS-SERVER01 Anonymous user The level is INFO, which means a detailed event; it says a request user from REST consumed the Parcels Map Service and GIS-SERVER01 served that request. If you have security enabled, you would even know which user consumed that service. Now, let us take it to the next level. On the Parcels REST page, click on ArcGIS JavaScript to view the map with the service loaded. Go back to the log view and click on Query to refresh; make sure the Log Filter dropdown is set to Verbose. A fleet of messages was generated from our last action; we will take a look at each line and analyze it. There are many columns that can be displayed on the log table and you can show or hide them from the Columns button. For a better view, you can click on the Printer Friendly View link, which will display a text format version of this table in a new page. This is the log we are going to analyze; we will start from the first line: INFO, Nov 17, 2013, 11:29:17 AM, Request user: Anonymous user, Service: Parcels/MapServer Rest. This is a request to consume the service. You can use this identifier to measure how many times a service has been requested. FINE Nov 17, 2013, 11:29:17 AM REST request received. Request size is 178 characters. Parcels.MapServer The preceding line is appended if there is more work to be followed; it shows the request size in bytes. FINE Nov 17, 2013, 11:29:17 AM Begin ExportMapImage Parcels.MapServer The process is so fast that we are still in the same second. The preceding line of code tells us that the Export Map Image process just started. This is the big process where Server exports an image of the desired area; however, there is still more work to follow to create the actual image. You can start measuring the drawing time of a certain service from this line. VERBOSE Nov 17, 2013, 11:29:17 AM Begining of preparation. Parcels.MapServer VERBOSE Nov 17, 2013, 11:29:17 AM End of preparation. Parcels.MapServer The preceding two lines highlight the preparation of the export image process. They usually happen very fast. FINE Nov 17, 2013, 11:29:17 AM Extent:1467314.863829,2191233.084700,2574598.328396,2702665.79038; Size:1574,727; Scale:2658831.00Parcels.MapServer A map needs an initial extent coordinates for it to draw. At the first call of the service, Server implicitly sends the default full extent to draw the map. After that, the user will explicitly request a new extent, each time he/she zooms in or pans the map. VERBOSE Nov 17, 2013, 11:29:17 AM Beginning of layer draw: Parcels Parcels.MapServer Since we only have one layer, you will see one occurrence of this line; however, you will see these lines reappear with more layers and there will be more logs to follow. VERBOSE Nov 17, 2013, 11:29:17 AM Execute Query Parcels.MapServer I consider this one of the most important lines; this is where the database is advised and queried to get the actual features. You can make a good measurement here by monitoring how long an execute query takes. If this takes a long time to execute, you might want to consult your DBA to look into tuning the database. VERBOSE Nov 17, 2013, 11:29:17 AM Symbol Drawing Parcels.MapServer VERBOSE Nov 17, 2013, 11:29:17 AM Data Access Parcels.MapServer VERBOSE Nov 17, 2013, 11:29:17 AM Symbolizing Parcels.MapServer Symbology work, depending on the user, can be executed either on the server or on the client. Since we are running on a browser, the symbology drawing will be carried on the client's browser by JavaScript. Note that this is only the symbology drawing; the labeling is done in another step. VERBOSE Nov 17, 2013, 11:29:17 AM Number of features drawn: 10 Parcels.MapServer This message shows the number of features that have been drawn. This line is useful if you want to know how many features are retrieved for each request and monitor the performance. VERBOSE Nov 17, 2013, 11:29:17 AM End of layer draw: Parcels Parcels.MapServer This line signifies the end of layer drawing; you should now start seeing the map, but with no labels. VERBOSE Nov 17, 2013, 11:29:17 AM Beginning of labeling phase (labeling and label draw) Parcels.MapServer Now that the symbology work is done, the labeling will start. This will give you even more measurement indicators for performance. VERBOSE Nov 17, 2013, 11:29:17 AM Symbol Drawing Parcels.MapServer It draws the font symbol as described in the layer description which can be found in the layer properties. VERBOSE Nov 17, 2013, 11:29:17 AM Number of features drawn: 10 Parcels.MapServer The preceding line indicates that the features have been labeled successfully. VERBOSE Nov 17, 2013, 11:29:17 AM End of labeling phase (labeling and label draw) Parcels.MapServer The preceding line marks the end of the labeling phase. FINE Nov 17, 2013, 11:29:17 AM End ExportMapImage Parcels.MapServer The map image has been exported successfully; we will attempt to deliver it to the client after this. FINE Nov 17, 2013, 11:29:17 AM REST request successfully processed. Response size is 6364 characters. Parcels.MapServer The last message describes the response map, which is a 6K map image. My Server is so fast that the whole thing happened in the same second. This is not much by way of a log analysis. However, in the next topic we will attempt to analyze a much richer log and will try to answer some questions.
Read more
  • 0
  • 0
  • 3176

article-image-intents-mobile-components
Packt
20 Jan 2014
7 min read
Save for later

Intents for Mobile Components

Packt
20 Jan 2014
7 min read
(For more resources related to this topic, see here.) Common mobile components Due to the open source nature of the Android operating system, many different companies such as HTC and Samsung ported the Android OS on their devices with many different functionalities and styles. Each Android phone is unique in some way or the other and possesses many unique features and components different from other brands and phones. But there are some components that are found to be common in all the Android phones. We are using two key terms here: components and features. Component is the hardware part of an Android phone, such as camera, Bluetooth and so on. And Feature is the software part of an Android phone, such as the SMS feature, E-mail feature, and so on. This article is all about hardware components, their access, and their use through intents. These common components can be generally used and implemented independently of any mobile phone or model. And there is no doubt that intents are the best asynchronous messages to activate these Android components. These intents are used to trigger the Android OS when some event occurrs and some action should be taken. Android, on the basis of the data received, determines the receiver for the intent and triggers it. Here are a few common components found in each Android phone: The Wi-Fi component Each Android phone comes with a complete support of the Wi-Fi connectivity component. The new Android phones having Android Version 4.1 and above support the Wi-Fi Direct feature as well. This allows the user to connect to nearby devices without the need to connect with a hotspot or network access point. The Bluetooth component An Android phone includes Bluetooth network support that allows the users of Android phones to exchange data wirelessly in low range with other devices. The Android application framework provides developers with the access to Bluetooth functionality through Android Bluetooth APIs. The Cellular component No mobile phone is complete without a cellular component. Each Android phone has a cellular component for mobile communication through SMS, calls, and so on. The Android system provides very high, flexible APIs to utilize telephony and cellular components to create very interesting and innovative apps. Global Positioning System (GPS) and geo-location GPS is a very useful but battery-consuming component in any Android phone. It is used for developing location-based apps for Android users. Google Maps is the best feature related to GPS and geo-location. Developers have provided so many innovative apps and games utilizing Google Maps and GPS components in Android. The Geomagnetic field component Geomagnetic field component is found in most Android phones. This component is used to estimate the magnetic field of an Android phone at a given point on the Earth and, in particular, to compute magnetic declination from the North. The geomagnetic field component uses the World Magnetic Model produced by United States National Geospatial-Intelligence Agency. The current model that is being used for the geomagnetic field is valid until 2015. Newer Android phones will have the newer version of the geomagnetic field. Sensor components Most Android devices have built-in sensors that measure motion, orientation, environment conditions, and so on. These sensors sometimes act as the brains of the app. For example, they take actions on the basis of the mobile's surrounding (weather) and allow users to have an automatic interaction with the app. These sensors provide raw data with high precision and accuracy for measuring the respective sensor values. For example, gravity sensor can be used to track gestures and motions, such as tilt, shake, and so on, in any app or game. Similarly, a temperature sensor can be used to detect the mobile temperature, or a geomagnetic sensor (as introduced in the previous section) can be used in any travel application to track the compass bearing. Broadly, there are three categories of sensors in Android: motion, position, and environmental sensors. The following subsections discuss these types of sensors briefly. Motion sensors Motion sensors let the Android user monitor the motion of the device. There are both hardware-based sensors such as accelerometer, gyroscope, and software-based sensors such as gravity, linear acceleration, and rotation vector sensors. Motion sensors are used to detect a device's motion including tilt effect, shake effect, rotation, swing, and so on. If used properly, these effects can make any app or game very interesting and flexible, and can prove to provide a great user experience. Position sensors The two position sensors, geomagnetic sensor and orientation sensor, are used to determine the position of the mobile device. Another sensor, the proximity sensor, lets the user determine how close the face of a device is to an object. For example, when we get any call on an Android phone, placing the phone on the ear shuts off the screen, and when we hold the phone back in our hands, the screen display appears automatically. This simple application uses the proximity sensor to detect the ear (object) with the face of the device (the screen). Environmental sensors These sensors are not used much in Android apps, but used widely by the Android system to detect a lot of little things. For example, the temperature sensor is used to detect the temperature of the phone, and can be used in saving the battery and mobile life. At the time of writing this article, the Samsung Galaxy S4 Android phone has been launched. The phone has shown a great use of environmental gestures by allowing users to perform actions such as making calls by no-touch gestures such as moving your hand or face in front of the phone. Components and intents Android phones contain a large number of components and features. This becomes beneficial to both Android developers and users. Android developers can use these mobile components and features to customize the user experience. For most components, developers get two options; either they extend the components and customize those according to their application requirements, or they use the built-in interfaces provided by the Android system. We won't read about the first choice of extending components as it is beyond the scope of this article. However, we will study the other option of using built-in interfaces for mobile components. Generally, to use any mobile component from our Android app, the developers send intents to the Android system and then Android takes the action accordingly to call the respective component. Intents are asynchronous messages sent to the Android OS to perform any functionality. Most of the mobile components can be triggered by intents just by using a few lines of code and can be utilized fully by developers in their apps. In the following sections of this article, we will see few components and how they are used and triggered by intents with practical examples. We have divided the components in three ways: communication components, media components, and motion components. Now, let's discuss these components in the following sections. Communication components Any mobile phone's core purpose is communication. Android phones provide a lot of features other than communication features. Android phones contain SMS/MMS, Wi-Fi, and Bluetooth for communication purposes. This article focuses on the hardware components; so, we will discuss only Wi-Fi and Bluetooth. The Android system provides built-in APIs to manage and use Bluetooth devices, settings, discoverability, and much more. It offers full network APIs not only for Bluetooth but also for Wi-Fi, hotspots, configuring settings, Internet connectivity, and much more. More importantly, these APIs and components can be used very easily by writing few lines of code through intents. We will start by discussing Bluetooth, and how we can use Bluetooth through intents in the next section.
Read more
  • 0
  • 0
  • 4591

article-image-search-using-beautiful-soup
Packt
20 Jan 2014
6 min read
Save for later

Search Using Beautiful Soup

Packt
20 Jan 2014
6 min read
(For more resources related to this topic, see here.) Searching with find_all() The find() method was used to find the first result within a particular search criteria that we applied on a BeautifulSoup object. As the name implies, find_all() will give us all the items matching the search criteria we defined. The different filters that we see in find() can be used in the find_all() method. In fact, these filters can be used in any searching methods, such as find_parents() and find_siblings(). Let us consider an example of using find_all(). Finding all tertiary consumers We saw how to find the first and second primary consumer. If we need to find all the tertiary consumers, we can't use find(). In this case, find_all() will become handy. all_tertiaryconsumers = soup.find_all(class_="tertiaryconsumerslist") The preceding code line finds all the tags with the = "tertiaryconsumerlist" class. If given a type check on this variable, we can see that it is nothing but a list of tag objects as follows: print(type(all_tertiaryconsumers)) #output <class 'list'> We can iterate through this list to display all tertiary consumer names by using the following code: for tertiaryconsumer in all_tertiaryconsumers: print(tertiaryconsumer.div.string) #output lion tiger Understanding parameters used with find_all() Like find(), the find_all() method also has a similar set of parameters with an extra parameter, limit, as shown in the following code line: find_all(name,attrs,recursive,text,limit,**kwargs) The limit parameter is used to specify a limit to the number of results that we get. For example, from the e-mail ID sample we saw, we can use find_all() to get all the e-mail IDs. Refer to the following code: email_ids = soup.find_all(text=emailid_regexp) print(email_ids) #output [u'abc@example.com',u'xyz@example.com',u'foo@example.com'] Here, if we pass limit, it will limit the result set to the limit we impose, as shown in the following example: email_ids_limited = soup.find_all(text=emailid_regexp,limit=2) print(email_ids_limited) #output [u'abc@example.com',u'xyz@example.com'] From the output, we can see that the result is limited to two. The find() method is find_all() with limit=1. We can pass True or False values to find the methods. If we pass True to find_all(), it will return all tags in the soup object. In the case of find(), it will be the first tag within the object. The print(soup.find_all(True)) line of code will print out all the tags associated with the soup object. In the case of searching for text, passing True will return all text within the document as follows: all_texts = soup.find_all(text=True) print(all_texts) #output [u'n', u'n', u'n', u'n', u'n', u'plants', u'n', u'100000', u'n', u'n', u'n', u'algae', u'n', u'100000', u'n', u'n', u'n', u'n', u'n', u'deer', u'n', u'1000', u'n', u'n', u'n', u'rabbit', u'n', u'2000', u'n', u'n', u'n', u'n', u'n', u'fox', u'n', u'100', u'n', u'n', u'n', u'bear', u'n', u'100', u'n', u'n', u'n', u'n', u'n', u'lion', u'n', u'80', u'n', u'n', u'n', u'tiger', u'n', u'50', u'n', u'n', u'n', u'n', u'n'] The preceding output prints every text content within the soup object including the new-line characters too. Also, in the case of text, we can pass a list of strings and find_all() will find every string defined in the list: all_texts_in_list = soup.find_all(text=["plants","algae"]) print(all_texts_in_list) #output [u'plants', u'algae'] This is same in the case of searching for the tags, attribute values of tag, custom attributes, and the CSS class. For finding all the div and li tags, we can use the following code line: div_li_tags = soup.find_all(["div","li"]) Similarly, for finding tags with the producerlist and primaryconsumerlist classes, we can use the following code lines: all_css_class = soup.find_all(class_=["producerlist","primaryconsumerlist"]) Both find() and find_all() search an object's descendants (that is, all children coming after it in the tree), their children, and so on. We can control this behavior by using the recursive parameter. If recursive = False, search happens only on an object's direct children. For example, in the following code, search happens only at direct children for div and li tags. Since the direct child of the soup object is html, the following code will give an empty list: div_li_tags = soup.find_all(["div","li"],recursive=False) print(div_li_tags) #output [] If find_all() can't find results, it will return an empty list, whereas find() returns None. Navigation using Beautiful Soup Navigation in Beautiful Soup is almost the same as the searching methods. In navigating, instead of methods, there are certain attributes that facilitate the navigation. So each Tag or NavigableString object will be a member of the resulting tree with the Beautiful Soup object placed at the top and other objects as the nodes of the tree. The following code snippet is an example for an HTML tree: html_markup = """<div class="ecopyramid"> <ul id="producers"> <li class="producerlist"> <div class="name">plants</div> <div class="number">100000</div> </li> <li class="producerlist"> <div class="name">algae</div> <div class="number">100000</div> </li> </ul> </div>""" For the previous code snippet, the following HTML tree is formed: In the previous figure, we can see that Beautiful Soup is the root of the tree, the Tag objects make up the different nodes of the tree, while NavigableString objects make up the leaves of the tree. Navigation in Beautiful Soup is intended to help us visit the nodes of this HTML/XML tree. From a particular node, it is possible to: Navigate down to the children Navigate up to the parent Navigate sideways to the siblings Navigate to the next and previous objects parsed We will be using the previous html_markup as an example to discuss the different navigations using Beautiful Soup. Summary In this article, we discussed in detail the different search methods in Beautiful Soup, namely, find(), find_all(), find_next(), and find_parents(); code examples for a scraper using search methods to get information from a website; and understanding the application of search methods in combination. We also discussed in detail the different navigation methods provided by Beautiful Soup, methods specific to navigating downwards and upwards, and sideways, to the previous and next elements of the HTML tree. Resources for Article: Further resources on this subject: Web Services Testing and soapUI [article] Web Scraping with Python [article] Plotting data using Matplotlib: Part 1 [article]
Read more
  • 0
  • 0
  • 8522

article-image-using-phalcon-models-views-and-controllers
Packt
20 Jan 2014
3 min read
Save for later

Using Phalcon Models, Views, and Controllers

Packt
20 Jan 2014
3 min read
(For more resources related to this topic, see here.) Creating CRUD scaffolding CRUD stands for create, read, update, and delete, which are the four basic functions our application should do with our blog post records. Phalcon web tools will also help us to get these built. Click on the Scaffold tab on the web tools page and you will see a page as shown in the following screenshot: Select posts from the Table name list and volt from the Template engine list, and check Force this time, because we are going to force our new files to overwrite the old model and controller files that we just generated. Click on the Generate button and some magic should happen. Browse to http://localhost/phalconBlog/posts and you will see a page like the following screenshot: We finally have some functionality we can use. We have no posts, but we can create some. Click on the Create posts link and you will see a page similar to the one we were just at. The form will look nearly the same, but it will have a Create posts heading. Fill out the Title, Body, and Excerpt fields and click on the Save button. The form will post, and you will get a message stating that the post was created successfully. This will take you back to the post's index page. Now you should be able to search for and find the post you just created. If you forgot what you posted, you can click on Search without entering anything in the fields, and you should see a page like the following screenshot: This is not a very pretty or user-friendly blog application. But it got us started, and that's all we need. The next time we start a Phalcon project, it should only take a few minutes to go through these steps. Now we will look over our generated code, and as we do, modify it to make it more blog-like. Summary In this article, we worked on the model, view, and controller for the posts in our blog. To do this, we used Phalcon web tools to generate our CRUD scaffolding for us. Then, we modified this generated code so it would do what we need it to do. We can now add posts. We also learned about the Volt template engine. Resources for Article: Further resources on this subject: Using An Object Oriented Approach for Implementing PHP Classes to Interact with Oracle [Article] FuelPHP [Article] Installing PHP-Nuke [Article]
Read more
  • 0
  • 0
  • 2996
article-image-grunt-action
Packt
20 Jan 2014
5 min read
Save for later

Grunt in Action

Packt
20 Jan 2014
5 min read
(For more resources related to this topic, see here.) Step 4 – optimizing our build files At this point, we should have a structured set of source files and can now perform additional transformations on the result. Let's start by downloading the plugins from npm and saving them in our package.json file: $ npm install --save-dev grunt-contrib-uglify grunt-contrib-cssmin grunt-contrib-htmlmin Then, at the top of our Gruntfile.js file, where we have loaded our other Grunt plugins, we will load our new additions with: grunt.loadNpmTasks("grunt-contrib-uglify"); grunt.loadNpmTasks("grunt-contrib-cssmin"); grunt.loadNpmTasks("grunt-contrib-htmlmin"); Scripts We will start by compressing our scripts. In this example, we use the grunt-contrib-uglify plugin http://gswg.io#grunt-contrib-uglify), which is a wrapper around the popular UglifyJS library (http://gswg.io#uglifyjs). Now we have loaded the plugin, which provides the uglify task, we just need to configure it: uglify: { compress: { src: "<%= coffee.build.dest %>", dest: "<%= coffee.build.dest %>" } } Here, inside the uglify property, we have made a compress target, which has src and dest set to the same file. Instead of entering the actual filename, we are making use of Grunt templates to retrieve the value at the given configuration path (coffee.build.dest), which in this case, resolves to build/js/app.js. Grunt templates make it easy to have a single source of truth within our configuration. Therefore, if we ever want to change the file path of our JavaScript, we only need to change one configuration entry. Since we have set the source and destination to the same file path, in effect, we are overwriting our JavaScript with the compressed version of itself. However, if we were writing a JavaScript library instead of a web application, we'd most likely want to compress our app.js file into an app.min.js file, so its users could download an uncompressed and a compressed version. Running this uglify task with this basic configuration should result in the following app.js file: (function(){var a,b;a=function(a,b){return a+b},b=function(a,b){return a-b},alert(a(7,b(4,1)))}).call(this); Generally, this will suffice, however, UglifyJS also offers advanced features. For example, in some cases, we might have portions of code that are only used during development. We could remove this unnecessary code with the following technique. By defining a DEBUG variable and place our debug-related code inside an if block as follows: if(DEBUG) { //do things here } Then, if we used the following options object inside our uglify configuration as follows: options: { compress: { global_defs: { "DEBUG": false }, dead_code: true } } This would result in UglifyJS locking the value of DEBUG to false and also to remove the inaccessible code (dead code). Therefore, in addition to compressing code, we also have the ability to completely remove code from our builds. The documentation for this feature can be found at http://gswg.io#grunt-contrib-uglify-conditional-compilation. Styles To compress our styles, we use the grunt-contrib-cssmin plugin (http://gswg.io#grunt-contrib-cssmin), which is a wrapper around the clean-css library (http://gswg.io#clean-css). Since we have installed this plugin, we just need to include the cssmin task configuration: cssmin: { compress: { src: "<%= stylus.build.dest %>", dest: "<%= stylus.build.dest %>" } } Similar to our scripts configuration, we can see that the only real difference is that we point to the stylus task's output instead of pointing to the coffee task's output. When we run grunt cssmin, our css/app.css file should be modified to the following one: html,body{margin:0;padding:0}.content .middle{font-size:16pt}@media (max-width:768px){.content .middle{font-size:8pt}} Views Finally, to compress our views, we will use the grunt-contrib-htmlmin plugin (http://gswg.io#grunt-contrib-htmlmin), which is a wrapper around the html-minifier library (http://gswg.io#html-minifier). The htmlmin configuration has a little more to it: since its compression options are disabled by default, we need to enable the rules we wish to use: htmlmin: { options: { removeComments: true, collapseWhitespace: true, collapseBooleanAttributes: true, removeAttributeQuotes: true, removeRedundantAttributes: true, removeOptionalTags: true }, compress: { src: "<%= jade.build.dest %>", dest: "<%= jade.build.dest %>" } } Now our htmlmin task is configured, we can run it with grunt htmlmin, which should modify our build/app.html to the following: <!DOCTYPE html><html><head><link rel=stylesheet href=css/app. css><body><section class=header>this is the <b>amazing</b> header section</section><section class=content><div class=top>some content with this on top</div><div class=middle>and this in the middle</ div><div class=bottom>and this on the bottom</div></section><section class=footer>and this is the footer, with an awesome copyright symbol with the year next to it - © 2013</section><script src = js/app. js></script> In addition to the GitHub repository, we can read more about html-minifier on Juriy "Kangax" Zaytsev's blog at http://gswg.io#experimenting-with-html-minifier. Summary In this article we performed additional transformations on set of source files by using Grunt. Resources for Article: Further resources on this subject: Trapping Errors by Using Built-In Objects in JavaScript Testing [article] Developing Wiki Seek Widget Using Javascript [article] Working with JavaScript in Drupal 6: Part 1 [article]
Read more
  • 0
  • 0
  • 1623

article-image-working-common-architectures
Packt
17 Jan 2014
10 min read
Save for later

Working with common architectures

Packt
17 Jan 2014
10 min read
(For more resources related to this topic, see here.) Working with a case structure Case structure is equivalent to a conditional statement in a text-based programming language. We will create a few case structures that take different kinds of inputs, such as Boolean, numeric, string, enum, and error, to present different features of a case structure. How to do it... We will start with a Boolean case structure. The case structure in the following block diagram shows a case structure taking a Boolean input. It consists of False and True cases. The select node is also in the diagram to show that it can be used instead of a case structure when the input is Boolean. The select node will choose which input to output based on the Boolean input, similar to the case structure. The case structure in the following block diagram takes an integer as input. Keep in mind that when the input is a floating point value, it is converted into an integer. The ..-1 case will be executed when the input is less than or equal to 1. The 1, 2 case will be executed when the input is 1 or 2. The 3..5 case will be executed when the input value is between 3 and 5 inclusively. The 6.. case will be executed when the input is greater than or equal to 6. The 0, Default case will be executed when the input is 0 or does not meet the conditions of all the other cases, which is what Default means in this case. The following block diagram shows a case structure with a string input. The ''a''..''f'' case will be executed when the ASCII hex value of the input string is between a and f, including a, but excluding f. The ''f''..''j'' case will be executed when the ASCII hex value of the input string is between f and j, including f, but excluding j. If the input value does not meet the conditions of the previous states, the Default case will run. The following block diagram shows a case structure with enum input. These cases will be executed based on the input value. The Case 1 case is assigned as the default case. If the input does not meet the condition of Case 2 and Case 3, Case 1 will run by default. Enum is used for state machine, as it allows for self-documenting code. The value of an enum is also part of its type, so if we add a value in an enum type-def, the change will propagate to the rest of the block diagram. The following block diagram contains an error cluster input. It has two cases: No Error and Error. It is used extensively in a SubVI for bypassing input error, so that it doesn't get corrupted inside the SubVI. How it works... Case structure is the main way to make decisions in LabVIEW's code. It can take different types of input, such as Boolean, numeric, string, enum, and error cluster. For the Boolean case structure, sometimes it is more convenient to use the select node. It is important to note that the case structure should not be nested with too many layers and each case should be documented. Working with an event structure Event structure consists of one or more cases. Codes that are contained within a case are executed when a control event (mouse click, key stroke, and so on) or a user event (software-based event) occurs. How to do it... We will create an example that demonstrates using control event and user event for the event structure. The following example contains a numeric control (Input Num). When a number is entered, an event is triggered. For the Input Text string control, if a string is entered, an event is triggered, but no text will show up, as all the events (entering text) are discarded. When the Switch Boolean control is clicked, an event is triggered. If any event is triggered, the string indicator (Action) will update with a string that states what event has occurred. The following screenshot shows the front panel of the controls and indicator: The following screenshot shows the block diagram of the example. On the left, a Create User Event node is used to create a user event that can be generated within the code. The input user event data type is the data type used for data passing for a user event. The label of the data type in our example is Stop User, which will be used as the name of the user event. The while loop at the bottom iterates once every 500 ms, and it will generate a user event if the stop Boolean control is set to true. The event reference is registered with the Register for Events node and fed into the dynamic event terminal, which needs to be enabled by right-clicking on the frame of the event structure and then select Show Dynamic Event Terminals. In the top while loop, we see the event case that handles the event when the value of the Boolean changes for the Switch control. It is a good practice to put the control associated with the event case into the case, so that the control is easy to find and it is read by the program every time the event is triggered. When the Boolean value changes, the Action string indicator will update to show what event has occurred. The event case in the following screenshot will be executed when a key is pressed within the Input Num numeric control. The Action string indicator will update and show that the event has occurred. To create the previous event case, right-click on the event structure and select Add Event Case…. The following screenshot shows how to set up the case. Select the Input Num numeric control under Event Source and then choose which type of event to handle. The event case in the following screenshot will execute when a key is pressed within the string control, similar to the event case for the numeric control. However, notice ? behind the label of the Key Down event. This is a filter event which can discard the outcome of the event, contrary to all the previous event cases which use notify event. While our example runs as we enter values into the string control, we see that the key down event happened at the string control in the Action string indicator. The entered values do not appear in the string controls as the events are discarded. Filter events give us the ability to trigger based on an event while discarding the event as though it never happened. Notify events will trigger based on an event without interfering with the occurrence of the event. The event case in the following screenshot will execute when a timeout event occurs. In this example, the timeout event will occur in 10000 ms, if no other events occur. We can change the timeout value as we wish. If we do not want the timeout event to trigger, we can wire a -1 to the timeout input. The event case in the following screenshot will execute when a user event is generated at the bottom while loop (refer to screenshot of the complete example). Recall that the name of the user event is the label of the data type when we created the user event. The user event is generated by the bottom loop when the stop Boolean control is set to true. This way both loops can stop each other's execution. If we have to create thirty event cases manually, it can be a lot of work. The following screenshot shows an example with thirty Boolean controls. For the example, we don't have to create thirty event cases for each Boolean control. The example gets all the references of the controls on the front panel as an array and registers all the references as a dynamic event. In this event case, if any of the Boolean controls has a value change event, the case will trigger. To get more resolution, we get the reference of the control for which the event originated from and print out a text. How it works... Whenever we find ourselves wanting to use a while loop to poll user for data, we should use the event structure instead. When the event structure is waiting for an event, it does not consume any CPU resources. Working with loops Loop is a common element in programming. In LabVIEW, there is for loop, while loop, and timed loop with features that facilitate LabVIEW programming. We will go over the for loop. For the while loop, its features are very similar to the for loop, so it is omitted. How to do it... The for loop is used when a predetermined number of iteration is needed. For an undetermined number of iteration, use the while loop instead. In the following screenshot, on the left, all the features of a for loop are shown; on the right is shown the result of the example. The input of the for loop is an array with elements 3 and 6. The entry point where the array enters the for loop is a [] symbol, which means autoindexing. When the array is autoindexed, each iteration of the for loop will get an element of the array in order. Since the loop is autoindexed, the N symbol (number of iteration) at the upper-left hand corner does not need to be wired. The loop will iterate through each element of the array. In our case, the for loop will iterate two times. If multiple arrays with different lengths are wired into the for loop through autoindex, the number of times that the for loop will iterate is the size of the array with the least number of elements. The i would output the current iteration of the loop, and the stop symbol allows the program to stop the loop before completion. For enabling the conditional stop, right-click on for loop and enable the Conditional terminal. The example shows four output options. To select an option, right-click on the output terminal, select Tunnel Mode, and then select the desired option. For the last value option, the value at the very end of the array is outputted. For the Indexing option, the same number of elements as the input is outputted. For the Conditional option, we can create conditions for which elements are built into the output array. For the Concatenation option, we can concatenate to the end of a 1D array. How it works... The for loop iterates over the same code for a predetermined number of times. If the Conditional terminal is enabled, the for loop can be stopped prematurely. The for loop has many features, such as outputting the value of last iteration, indexing through an array (with and without a condition), and concatenating an array, that are useful for array processing.
Read more
  • 0
  • 0
  • 2574

article-image-bsd-socket-library
Packt
17 Jan 2014
9 min read
Save for later

BSD Socket Library

Packt
17 Jan 2014
9 min read
(For more resources related to this topic, see here.) Introduction The Berkeley Socket API (where API stands for Application Programming Interface) is a set of standard functions used for inter-process network communications. Other socket APIs also exist; however, the Berkeley socket is generally regarded as the standard. The Berkeley Socket API was originally introduced in 1983 when 4.2 BSD was released. The API has evolved with very few modifications into a part of the Portable Operating System Interface for Unix (POSIX) specification. All modern operating systems have some implementation of the Berkeley Socket Interface for connecting devices to the Internet. Even Winsock, which is MS Window's socket implementation, closely follows the Berkeley standards. BSD sockets generally rely on client/server architecture when they establish their connections. Client/server architecture is a networking approach where a device is assigned one of the two following roles: Server: A server is a device that selectively shares resources with other devices on the network Client: A client is a device that connects to a server to make use of the shared resources Great examples of the client/server architecture are web pages. When you open a web page in your favorite browser, for example https://www.packtpub.com, your browser (and therefore your computer) becomes the client and Packt Publishing's web servers become the servers. One very important concept to keep in mind is that any device can be a server, a client, or both. For example, you may be visiting the Packt Publishing website, which makes you a client, and at the same time you have file sharing enabled, which also makes your device a server. The Socket API generally uses one of the following two core protocols: Transmission Control Protocol (TCP): TCP provides a reliable, ordered, and error-checked delivery of a stream of data between two devices on the same network. TCP is generally used when you need to ensure that all packets are correctly received and are in the correct order (for example, web pages). User Datagram Protocol (UDP): UDP does not provide any of the error-checking or reliability features of TCP, but offers much less overhead. UDP is generally used when providing information to the client quickly is more important than missing packets (for example, a streaming video). Darwin, which is an open source POSIX compliant operating system, forms the core set of components upon which Mac OS X and iOS are based. This means that both OS X and iOS contain the BSD Socket Library. The last paragraph is very important to understand when you begin thinking about creating network applications for the iOS platform, because almost any code example that uses the BSD Socket Library will work on the iOS platform. The biggest difference between using the BSD Socket API on any standard Unix platform and the iOS platform is that the iOS platform does not support forking of processes. You will need to use multiple threads rather than multiple processes. The BSD Socket API can be used to build both client and server applications. There are a few networking concepts that you should understand: IP address: Any device on an Internet Protocol (IP) network, whether it is a client or server, has a unique identifier known as an IP address. The IP address serves two basic purposes: host identification and location identification. There are currently two IP address formats: IPv4: This is currently the standard for the Internet and most internal intranets. This is an example of an IPv4 address: 83.166.169.231. IPv6: This is the latest revision of the Internet Protocol (IP). It was developed to eventually replace IPv4 and to address the long-anticipated problem of running out of IPv4 addresses. This is an example of an IPv6 address: 2001:0db8:0000:0000:0000:ff00:0042:8329. An IPv6 can be shortened by replacing all the consecutive zero fields with two colons. The previous address could be rewritten as 2001:0db8::ff00:0042:8329. Ports: A port is an application or process-specific software construct serving as a communications endpoint on a device connected to an IP network, where the IP address identifies the device to connect to, and the port number identifies the application to connect to. The best way to think of network addressing is to think about how you mail a letter. For a letter to reach its destination, you must put the complete address on the envelope. For example, if you were going to send a letter to friend who lived at the following address: Your Friend 123 Main St Apt. 223 San Francisco CA, 94123 If I were to translate that into network addressing, the IP address would be equal to the street address, city, state, and zip code (123 Main St, San Francisco CA, 94123), and the apartment number would be equal to the port number (223). So the IP address gets you to the exact location, and the port number will tell you which door to knock on. A device has 65,536 available ports with the first 1024 being reserved for common protocols such as HTTP, HTTPS, SSH, and SMTP. Fully Qualified Domain Name (FQDN): As humans, we are not very good at remembering numbers; for example, if your friend tells you that he found a really excellent website for books and the address was 83.166.169.231, you probably would not remember that two minutes from now. However, if he tells you that the address was www.packtpub.com, you would probably remember it. FQDN is the name that can be used to refer to a device on an IP network. So now you may be asking yourself, how does the name get translated to the IP address? The Domain Name Server (DNS) would do that. Domain Name System Servers: A Domain Name System Server translates a fully qualified domain name to an IP address. When you use an FQDN of www.packtpub.com, your computer must get the IP address of the device from the DNS configured in your system. To find out what the primary DNS is for your machine, open a terminal window and type the following command: cat /etc/resolv.conf Byte order: As humans, when we look at a number, we put the most significant number first and the least significant number last; for example, in number 123, 1 represents 100, so it is the most significant number, while 3 is the least significant number. For computers, the byte order refers to the order in which data (not only integers) is stored into memory. Some computers store the most significant bytes first (at the lowest byte address), while others store the most significant bytes last. If a device stores the most significant bytes first, it is known as big-endian, while a device that stores the most significant bytes last is known as little-endian. The order of how data is stored in memory is of great importance when developing network applications, where you may have two devices that use different byte-ordering communication. You will need to account for this by using the Network-to-Host and Host-to-Network functions to convert between the byte order of your device and the byte order of the network. The byte order of the device is commonly referred to as the host byte order, and the byte order of the network is commonly referred to as the network byte order. Finding the byte order of your device One of the concepts that was briefly discussed in this article was how devices store information in memory (byte order). After that discussion, you may be wondering what the byte order of your device is. The byte order of a device depends on the Microprocessor architecture being used by the device. You can pretty easily go on to the Internet and search for "Mac OS X i386 byte order" and find out what the byte order is, but where is the fun in that? We are developers, so let's see if we can figure it out with code. We can determine the byte order of our devices with a few lines of C code; however, like most of the code in this article, we will put the C code within an Objective-C wrapper to make it easy to port to your projects. How to do it… Let's get started by defining an ENUM in our header file: We create an ENUM that will be used to identify the byte order of the system as shown in the following code: typedef NS_ENUM(NSUInteger, EndianType) { ENDIAN_UNKNOWN, ENDIAN_LITTLE, ENDIAN_BIG }; To determine the byte order of the device, we will use the byteOrder method as shown in the following code: -( EndianType)byteOrder { union { short sNum; char cNum[sizeof(short)]; } un; un.sNum = 0x0102; if (sizeof(short) == 2) { if(un.cNum[0] == 1 && un.cNum[1] == 2) return ENDIAN_BIG; else if (un.cNum[0] == 2 && un.cNum[1] == 1) return ENDIAN_LITTLE; else return ENDIAN_UNKNOWN; } else return ENDIAN_UNKNOWN; } How it works… In the ByteOrder header file, we defined an ENUM with three constants. The constants are as follows: ENDIAN_UNKNOWN: We are unable to determine the byte order of the device ENDIAN_LITTLE: This specifies that the most significant bytes are last (little-endian) ENDIAN_BIG: This specifies that the most significant bytes are first (big-endian) The byteOrder method determines the byte order of our device and returns an integer that can be translated using the constants defined in the header file. To determine the byte order of our device, we begin by creating a union of short int and char[]. We then store the value 0x0102 in the union. Finally, we look at the character array to determine the order in which the integer was stored in the character array. If the number one was stored first, it means that the device uses big-endian; if the number two was stored first, it means that the device uses little-endian.
Read more
  • 0
  • 0
  • 12273
article-image-creating-basic-javascript-plugin
Packt
17 Jan 2014
9 min read
Save for later

Creating a basic JavaScript plugin

Packt
17 Jan 2014
9 min read
(For more resources related to this topic, see here.) Getting started with an empty plugin To get started, create three files called manifest.xml, MyCompany.WebAccess.Plugin.debug.js, and MyCompany.WebAccess.Plugin.min.js. In the manifest.xml file, place the following XML: <WebAccess version="12.0"> <plugin name="MyCompany Plugin - Web Access" vendor="Gordon Beeming" moreinfo="http://31og.com" version="1.0"> <modules> <module namespace="MyCompany.WebAccess.Plugin" loadAfter="TFS.Agile.TaskBoard.View"/> <module namespace="MyCompany.WebAccess.Plugin" loadAfter="TFS.Agile.Boards.Controls"/> </modules> </plugin> </WebAccess> In the preceding code, once the plugin node has the attributes name, vendor, moreinfo, and version, we will be able to easily identify our plugin in the TFS Web Access admin area. Under the modules node, you will see that we have added two child module nodes. This informs TFS that we want to load our MyCompany.WebAccess.Plugin namespace after the TFS.Agile.TaskBoard.View and TFS.Agile.Boards.Controls namespaces, which are namespaces loaded on the task board and portfolio boards. You can get the base of this plugin from the sample code in the MyCompany.WebAccess.Plugin - Base.js file. If you have used the RequireJs module loader, you will notice that this syntax is very familiar. In the base code, you will see a bit of code like the following: TfsWebAccessPlugin.prototype.initialize = function () { // place code here to get started alert('MyCompany.WebAccess.Plugin is running'); }; This initialize method is where you start gaining control of what is happening in Web Access. Take all the code in the base code and place it in the debug.js file. Importing a plugin into TFS Web Access The first part of importing a plugin into TFS is to make sure that you have placed a minified version of your *.debug.js contents into your *.min.js file. Update the version of your plugin in the manifest.xml file, if required; for now, we will leave it at 1.0. Zip the three files we created; the name of this ZIP file doesn't make a difference to the usage of the plugin. Browse to the server's home page and then click on the Administer Server button in the top-right corner as shown in the following screenshot: The Administer Server Button Click on the Extensions tab and then click on Install . In the model window, click on browse to browse for the ZIP file you created with the contents of the plugin and then click on OK . You will now see that the plugin is visible in the extensions screen but is currently not enabled. Click on Enable and then on OK to enable it, as shown in the following screenshot: Web access extension when disabled When you navigate to any of the boards, you will see the alert that we placed in the initialize function. Setting up the debug mode We have just imported our plugin into TFS, and this was quite a long process. Although it is fine if we upload our plugin into an environment, when we have finished creating our plugin, it becomes very time consuming when we need to make changes to the plugin. You have to go through this whole process to see the changes. So, we will use some tricks that will help us debug our extension. Enabling the Script Debug Mode Navigate to the TFS URL with _diagnostics appended at the end, that is, http://gordon-pc:8080/tfs/_diagnostics. On this page, we will click on the Script Debug Mode link, which should currently be disabled. This should also switch Client Trace Point Collector to Enabled , as shown in the following screenshot: TFS diagnostics settings This will now make TFS use the debug.js file instead of the min.js file. You will also see more requests for JavaScript files as each file is now streamed separately instead of being bundled together for better load performance. For this reason, it is probably very clear that this should not be enabled on a production environment. Configuring a Fiddler AutoResponder rule The next part is to configure Fiddler to automatically respond to any requests for your plugin from the server with your local debug.js file. You can download Fiddler from http://fiddler2.com/. We are going to use Fiddler to intercept the request for our plugins' JavaScript file from TFS and use our local version of the plugin. The first step would be to start up Fiddler and make sure you can see the request for the MyCompany.WebAccess.Plugin.js file, which should have a URL similar to http://gordon-pc:8080/tfs/_static/tfs/12/_scripts/TFS/debug//tfs/_plugins/1957/MyCompany.WebAccess.Plugin.js. In Fiddler, switch to the AutoResponder tab and check Enable automatic responses and Unmatched requests passthrough . Now click on Add Rule and in the Rule editor menu, use the regex:http://gordon-pc:8080/tfs/_static/tfs/12/_scripts/TFS/.+/MyCompany.WebAccess.Plugin.js rule; this will put a wildcard on the mode and plugin ID that is being used currently. In the second textbox, write down the full location of the debug.js file for this plugin and then click on Save . Add a second rule in the same pattern, but this time in the second textbox, use header:CachControl=no-cache and click on Save . You should see something similar to the following screenshot in Fiddler: Fiddler AutoResponder rule added This will now make Web Access use your local debug.js file for all requests for the plugin in TFS. To try this out, go to the debug.js file, change the alert to we have added debugging , and save the file. Refresh the board, and you will see that without any additional effort, the alert changed. Adding information to display work items We will be going through some of the snippets that make a difference and are crucial to our plugin working correctly. The easiest way to make use of these types of plugins is to change the HTML based on the information available in the HTML; this is useful for small changes, such as displaying the ID of work items on the work item cards on the boards. For this, you would, on initialization of your plugin, use the setInterval function in JavaScript and call the following function every 500 milliseconds: function TaskBoardFunctions() { //replace IDs for tasks $("#taskboard-table .tbTile").each(function () { var id = $(this).attr("id"); id = id.split('-')[1]; $(this).find(".tbTileContent .witTitle").html("<span style='font-weight:bold;'>" + id + "</span> - " + $(this).find(".witTitle").html()); }); //replace IDs for tasks $("#taskboard-table .taskboard-row .taskboard-parent").each(function () { var id = $(this).attr("id"); if (id != undefined) { id = id.split('_')[1]; id = id.substring(1); $(this).find(".witTitle").html("<span style='font-weight:bold;'>" + id + "</span> - " + $(this).find(".witTitle").html()); } }); } This function just looks for all work items on the page using the IDs that are specified in the attributes in the HTML elements to add the IDs to the UI. A better way to do this would be to make use of the events in the API, and only make modifications to the displayed information when necessary. You would still use something similar to the preceding code for your initial loading to go through the board, and set all the information you would want to display; however, you would reply on the events to do any further updates. So, in this case, we would use the preceding code to scan for all the IDs on the page and then pass that through to a method, such as the following one, which will query the work item store. TFS has a configurable value that tells us the number of results that can be returned per query through the JavaScript API, and for this reason, we query 100 work items at a time; however, you can change this if it's not applicable to your plugin. Core.prototype.loadWorkItemsWork = function (idsToFetch, onComplete, that) { var takeAmount = 100; if (takeAmount >= idsToFetch.length) { takeAmount = idsToFetch.length; } if (takeAmount > 0) { that.WorkItemManager.store.beginPageWorkItems(idsToFetch.splice(0,takeAmount), [ "System.Id", "System.State" ], function (payload) { that.loadWorkItemsWork(idsToFetch, onComplete, that); $.each(payload.rows, function (index, row) { onComplete(index, row, that); }); }, function (err) { that.loadWorkItemsWork(idsToFetch, onComplete, that); alert(err); }); } }; As you can see, we are querying the work item store for the ID and the state of each work item on the page. We are then passing this off to an onComplete function that is using jQuery to find the elements by ID. We then alter the displayed information to show the ID, and on the task board to show the state of the requirement. If you use all the sample code and upload it into TFS, you will see a portfolio board like the one shown in the following screenshot: IDs on the portfolio board And on the task board, you will see the following screenshot: IDs and State on task board You can see that the tasks have IDs on them, which are the same as the portfolio boards, and the requirements listed on the left have IDs and their current states. Summary In this article, we covered customizing the TFS dashboard to display information that helps us find out a team's current status by pinning queries, build status, and recent changes to the source code. We then made some changes to the columns displayed in the portfolio backlog and the quick add panel. We finished off by going through what is required to create a TFS Web Access plugin. Resources for Article : Further resources on this subject: Ensuring Quality for Unit Testing with Microsoft Visual Studio 2010 [Article] Team Foundation Server 2012 [Article] The Command Line [Article]
Read more
  • 0
  • 0
  • 6919

article-image-integrating-direct3d-xaml-and-windows-81
Packt
16 Jan 2014
9 min read
Save for later

Integrating Direct3D with XAML and Windows 8.1

Packt
16 Jan 2014
9 min read
(For more resources related to this topic, see here.) Preparing the swap chain for a Windows Store app Getting ready To target Windows 8.1, we need to use Visual Studio 2013. For the remainder of the article, we will assume that these can be located upon navigating to .ExternalBinDirectX11_2-Signed-winrt under the solution location. How to do it… We'll begin by creating a new class library and reusing a majority of the Common project used throughout the book so far, then we will create a new class D3DApplicationWinRT inheriting from D3DApplicationBase to be used as a starting point for our Windows Store app's render targets. Within Visual Studio, create a new Class Library (Windows Store apps) called Common.WinRT. New Project dialog to create a class library project for Windows Store apps Add references to the following SharpDX assemblies: SharpDX.dll, SharpDX.D3DCompiler.dll, SharpDX.Direct2D1.dll, SharpDX.Direct3D11.dll, and SharpDX.DXGI within .ExternalBinDirectX11_2-Signed-winrt. Right-click on the new project; navigate to Add | Existing item... ; and select the following files from the existing Common project: D3DApplicationBase.cs, DeviceManager.cs, Mesh.cs, RendererBase.cs, and HLSLFileIncludeHandlers.hlsl, and optionally, FpsRenderer.cs and TextRenderer.cs. Instead of duplicating the files, we can choose to Add As Link within the file selection dialog, as shown in the following screenshot: Files can be added as a link instead of a copy Any platform-specific code can be wrapped with a check for the NETFX_CORE definition, as shown in the following snippet: #if NETFX_CORE ...Windows Store app code #else ...Windows Desktop code #endif Add a new C# abstract class called D3DApplicationWinRT. // Implements support for swap chain description for // Windows Store apps public abstract class D3DApplicationWinRT : D3DApplicationBase { ... } In order to reduce the chances of our app being terminated to reclaim system resources, we will use the new SharpDX.DXGI.Device3.Trim function whenever our app is suspended (native equivalent is IDXGIDevice3::Trim). The following code shows how this is done: public D3DApplicationWinRT() : base() { // Register application suspending event Windows.ApplicationModel.Core .CoreApplication.Suspending += OnSuspending; } // When suspending hint that resources may be reclaimed private void OnSuspending(Object sender, Windows.ApplicationModel.SuspendingEventArgs e) { // Retrieve the DXGI Device3 interface from our // existing Direct3D device. using (SharpDX.DXGI.Device3 dxgiDevice = DeviceManager .Direct3DDevice.QueryInterface<SharpDX.DXGI.Device3>()) { dxgiDevice.Trim(); } } The existing D3DApplicationBase.CreateSwapChainDescription function is not compatible with Windows Store apps. Therefore, we will override this and create a SwapChainDescription1 instance that is compatible with Windows Store apps. The following code shows the changes necessary: protected override SharpDX.DXGI.SwapChainDescription1 CreateSwapChainDescription() { var desc = new SharpDX.DXGI.SwapChainDescription1() { Width = Width, Height = Height, Format = SharpDX.DXGI.Format.B8G8R8A8_UNorm, Stereo = false, SampleDescription.Count = 1, SampleDescription.Quality = 0, Usage = SharpDX.DXGI.Usage.BackBuffer | SharpDX.DXGI.Usage.RenderTargetOutput, Scaling = SharpDX.DXGI.Scaling.Stretch, BufferCount = 2, SwapEffect = SharpDX.DXGI.SwapEffect.FlipSequential, Flags = SharpDX.DXGI.SwapChainFlags.None }; return desc; } We will not be implementing the Direct3D render loop within a Run method for our Windows Store apps—this is because we will use the existing composition events where appropriate. Therefore, we will create a new abstract method Render and provide a default empty implementation of Run. public abstract void Render(); [Obsolete("Use the Render method for WinRT", true)] public override void Run() { } How it works… As of Windows 8.1 and DirectX Graphics Infrastructure (DXGI) 1.3, all Direct3D devices created by our Windows Store apps should call SharpDX.DXGI.Device3.Trim when suspending to reduce the memory consumed by the app and graphics driver. This reduces the chance that our app will be terminated to reclaim resources while it is suspended—although our application should consider destroying other resources as well. When resuming, drivers that support trimming will recreate the resources as required. We have used Windows.ApplicationModel.Core.CoreApplication rather than Windows.UI.Xaml.Application for the Suspending event, so that we can use the class for both an XAML-based Direct3D app as well as one that implements its own Windows.ApplicationModel.Core.IFrameworkView in order to render to CoreWindow directly. Windows Store apps only support a flip presentation model and therefore require that the swap chain is created using a SharpDX.DXGI.SwapEffect.FlipSequential swap effect; this in turn requires between two and 16 buffers specified in the SwapChainDescription1.BufferCount property. When using a flip model, it is also necessary to specify the SwapChainDescription1.SampleDescription property with Count=1 and Quality=0, as multisample anti-aliasing (MSAA) is not supported on the swap chain buffers themselves. A flip presentation model avoids unnecessarily copying the swap-chain buffer and increases the performance. By removing Windows 8.1 specific calls (such as the SharpDX.DXGI.Device3.Trim method), it is also possible to implement this recipe using Direct3D 11.1 for Windows Store apps that target Windows 8. See also The Rendering to a CoreWindow and Rendering to a SwapChainPanel recipes show how to create swap chains for non-XAML and XAML apps respectively NuGet Package Manager can be downloaded from http://visualstudiogallery.msdn.microsoft.com/4ec1526c-4a8c-4a84-b702-b21a8f5293ca You can find the flip presentation model on MSDN at http://msdn.microsoft.com/en-us/library/windows/desktop/hh706346(v=vs.85).aspx Rendering to a CoreWindow The XAML view provider found in the Windows Store app graphics framework cannot be modified. Therefore, when we want to implement the application's graphics completely within DirectX/Direct3D without XAML interoperation, it is necessary to create a basic view provider that allows us to connect our DirectX graphics device resources to the windowing infrastructure of our Windows Store app. In this recipe, we will implement a CoreWindow swap-chain target and look at how to hook Direct3D directly to the windowing infrastructure of a Windows Store app, which is exposed by the CoreApplication, IFrameworkViewSource, IFrameworkView, and CoreWindow .NET types. This recipe continues from where we left off with the Preparing the swap chain for Windows Store apps recipe. How to do it… We will first update the Common.WinRT project to support the creation of a swap chain for a Windows Store app's CoreWindow instance and then implement a simple Hello World application. Let's begin by creating a new abstract class within the Common.WinRT project, called D3DAppCoreWindowTarget and descending from the D3DApplicationWinRT class from our previous recipe. The default constructor accepts the CoreWindow instance and attaches a handler to its SizeChanged event. using Windows.UI.Core; using SharpDX; using SharpDX.DXGI; ... public abstract class D3DAppCoreWindowTarget : D3DApplicationWinRT { // The CoreWindow this instance renders to private CoreWindow _window; public CoreWindow Window { get { return _window; } } public D3DAppCoreWindowTarget(CoreWindow window) { _window = window; Window.SizeChanged += (sender, args) => { SizeChanged(); }; } ... } Within our new class, we will now override the CurrentBounds property and the CreateSwapChain function in order to return the correct size and create the swap chain for the associated CoreWindow. // Retrieve current bounds of CoreWindow public override SharpDX.Rectangle CurrentBounds { get { return new SharpDX.Rectangle( (int)_window.Bounds.X, (int)_window.Bounds.Y, (int)_window.Bounds.Width, (int)_window.Bounds.Height); } } // Create the swap chain protected override SharpDX.DXGI.SwapChain1 CreateSwapChain( SharpDX.DXGI.Factory2 factory, SharpDX.Direct3D11.Device1 device, SharpDX.DXGI.SwapChainDescription1 desc) { // Create the swap chain for the CoreWindow using (var coreWindow = new ComObject(_window)) return new SwapChain1(factory, device, coreWindow, ref desc); } This completes the changes to our Common.WinRT project. Next, we will create a Hello World Direct3D Windows Store app rendering directly to the application's CoreWindow instance. Visual Studio 2013 does not provide us with a suitable C# project template to create a non-XAML Windows Store app, so we will begin by creating a new C# Windows Store Blank App (XAML) project. Add references to the SharpDX assemblies: SharpDX.dll, SharpDX.Direct3D11.dll, SharpDX.D3DCompiler.dll, and SharpDX.DXGI.dll. Also, add a reference to the Common.WinRT project. Next, we remove the two XAML files from the project: App.xaml and MainPage.xaml. We will replace the previous application entry point, App.xaml, with a new static class called App. This will house the main entry point for our application where we start our Windows Store app using a custom view provider, as shown in the following snippet: using Windows.ApplicationModel.Core; using Windows.Graphics.Display; using Windows.UI.Core; ... internal static class App { [MTAThread] private static void Main() { var viewFactory = new D3DAppViewProviderFactory(); CoreApplication.Run(viewFactory); } // The custom view provider factory class D3DAppViewProviderFactory : IFrameworkViewSource { public IFrameworkView CreateView() { return new D3DAppViewProvider(); } } class D3DAppViewProvider : SharpDX.Component, IFrameworkView { ... } } The implementation of the IFrameworkView members of D3DAppViewProvider allows us to initialize an instance of a concrete descendent of the D3DAppCoreWindowTarget class within SetWindow and to implement the main application loop in the Run method. Windows.UI.Core.CoreWindow window;D3DApp d3dApp; // descends from D3DAppCoreWindowTarget public void Initialize(CoreApplicationView applicationView) { } public void Load(string entryPoint) { } public void SetWindow(Windows.UI.Core.CoreWindow window) { RemoveAndDispose(ref d3dApp); this.window = window; d3dApp = ToDispose(new D3DApp(window)); d3dApp.Initialize(); } public void Uninitialize() { } public void Run() { // Specify the cursor type as the standard arrow. window.PointerCursor = new CoreCursor( CoreCursorType.Arrow, 0); // Activate the application window, making it visible // and enabling it to receive events. window.Activate(); // Set the DPI and handle changes d3dApp.DeviceManager.Dpi = Windows.Graphics.Display .DisplayInformation.GetForCurrentView().LogicalDpi; Windows.Graphics.Display.DisplayInformation .GetForCurrentView().DpiChanged += (sender, args) => { d3dApp.DeviceManager.Dpi = Windows.Graphics.Display .DisplayInformation.GetForCurrentView().LogicalDpi; }; // Enter the render loop. Note that Windows Store apps // should never exit here. while (true) { // Process events incoming to the window. window.Dispatcher.ProcessEvents( CoreProcessEventsOption.ProcessAllIfPresent); // Render frame d3dApp.Render(); } } The D3DApp class follows the same structure from our previous recipes throughout the book. There are only a few minor differences as highlighted in the following code snippet: class D3DApp: Common.D3DAppCoreWindowTarget { public D3DApp(Windows.UI.Core.CoreWindow window) : base(window) { this.VSync=true; } // Private member fields ... protected override void CreateDeviceDependentResources( Common.DeviceManager deviceManager) { ... create all device resources ... and create renderer instances here } // Render frame public override void Render() { var context = this.DeviceManager.Direct3DContext; // OutputMerger targets must be set every frame context.OutputMerger.SetTargets( this.DepthStencilView, this.RenderTargetView); // Clear depthstencil and render target context.ClearDepthStencilView( this.DepthStencilView, SharpDX.Direct3D11.DepthStencilClearFlags.Depth | SharpDX.Direct3D11.DepthStencilClearFlags.Stencil , 1.0f, 0); context.ClearRenderTargetView( this.RenderTargetView, SharpDX.Color.LightBlue); ... setup context pipeline state ... perform rendering commands // Present the render target Present(); } } The following screenshot shows an example of the output using CubeRenderer, and overlaying the 2D text with the TextRenderer class: Output from the simple Hello World sample using the CoreWindow render target
Read more
  • 0
  • 0
  • 3025
Modal Close icon
Modal Close icon