Click here to Skip to main content
15,867,308 members
Articles / Programming Languages / C#

The Kitchen Sink

Rate me:
Please Sign up or sign in to vote.
5.00/5 (8 votes)
17 Dec 2014CPOL8 min read 20.9K   12  
APOD, Horoscopes, Weather Radar, Windyty, Tech Feeds, Chromium, NOAA Weather

Image 1

Obtaining the Source

The source for this release is hosted on GitHub:

First, clone the repo: https://github.com/cliftonm/HOPE.git

Second, check out the "release-12-17-2014" branch.

Introduction

HOPE (Higher Order Programming Environment) is rapidly evolving into a highly configurable multi-purpose interactive application.  How's that for buzzword bingo?  Recently, I added a second "form" for the receptor user interfaces, also a dockable form.  This lets me create the user experience that I want -- what windows go where, whether they're tabbed, docked, or floating.

One of the things that happens is the browsing experience is taken out of the one-dimensional world of linear tabs across the top of the screen.  Instead, I can utilize the 2D screen surface more efficiently by showing multiple browser windows in different locations.  The same can be said of the other application user experiences as well -- image viewers, RSS feeds, text displays, etc. 

This article isn't so much about code as it is about the cool things you can do with HOPE, and more importantly, with semantic data.  Semantic data isn't just useful for data mining, it informs your code as the type of data, so that your code can do more interesting things with the data.  We'll demonstrate that later.

If this is your first time encountering HOPE, I highly recommend you read the following articles first:

Why The Kitchen Sink?

This screenshot above illustrates several different "applications":

  • RSS of some technical feeds with a semantic database backend, also double clicking on a feed brings up the page in the applet, rather than a separate browser
  • Radar scraped from NOAA radar weather page
  • The windyty website showing wind predictions
  • APOD scraper, showing the APOD image and, if I double-click on the image, brings up the APOD webpage for that image
  • My and my girlfriend's horoscope
  • The weather conditions for the day, acquired from the NOAA web service.
  • Oh, and if you want, it can talk to you too.

So, there's a lot going on in a single application, and it's all based on semantic data "signals" embedded into "carriers" that interact with runtime loaded "receptors" -- in other words, an architecture that is anything but monolithic in nature:

Image 2

The remainder of this article will show how each of these applets is created in HOPE, and where there's something interesting and new code-wise, I'll show that too.

APOD Scraper & Viewer

The View:

Image 3

The Applet:

Image 4

The APOD scraper and viewer applet consists of four receptors:

  1. APOD - scrapes the returned HTML to compose the radar image

  2. Webpage Scraper - a general purpose receptor that returns a page's HTML

  3. Image Viewer - a general purpose receptor that displays an image

  4. Web Page Viewer - a general purpose receptor that displays a web page in a Chromium browser window

Membranes are used to isolate semantic elements from other receptors.  You can read more about this in the tutorial: Excluding Semantic Sub-types with Membranes Boundaries

Functionally, this applet performs the following:

  1. The URL for the web page is formed from today's date

  2. The web page's HTML is acquired, which the APOD receptor receives back

  3. After building the composite image, the image is emitted

  4. The image is received by the Image Viewer.  Because the signal's parent is, semantically, a "WebImage", the image viewer will also emit the URL when the user double-clicks on the image.

  5. The emitted URL is received by the web page viewer, which displays the page.

So, for example, if I double-click on the image, I can read the description on the APOD website itself:

Image 5

Of course, being a dockable UI, I have complete control over where the page is displayed.

Emitting the URL:

public override void EndSystemInit()
{
  // Get today's image.
  string url = "http://apod.nasa.gov/apod/ap" + DateTime.Now.ToString("yyMMdd") + ".html";
  EmitUrl(url);
}

protected void EmitUrl(string url)
{
  CreateCarrier("Url", signal => signal.Value = url);
}

Scraping the resulting HTML is described in my article here.

Once the image has been composed, it is emitted as a WebImage semantic type:

protected void EmitImage(Image image, string title, string url)
{
  CreateCarrier("WebImage", signal =>
  {
     signal.Image.Value = image as Image;
     signal.Image.Title.Text.Value = title;
     signal.Url.Value = url;
  });
}

The image viewer receptor however only listens to "Image" semantic types.  This is a sub-type of the WebImage semantic type:

Image 6

The "Image" semantic type consists of the "Value" (a .NET native Image type) and a Title, which itself is a semantic type of "Text" having a native type "Value".

Image 7

The image viewer receptor handles the image directly from the Image semantic type "receiver":

AddReceiveProtocol("Image", (Action<dynamic>)(signal =>
{
  form.IfNull(() =>
  {
    InitializeUI();
    form.FormClosing += WhenFormClosing;
    form.SizeChanged += ProportionalResize;
  });

  pb.Image = signal.Value;
  string title = signal.Title.Text.Value;

  if (!String.IsNullOrEmpty(title))
  {
    WindowName = title;
    UpdateCaption();
  }
}));

However, it also overrides the lower-level ProcessCarrier method and tests for the existence of a parent carrier.  If this carrier is a WebImage, it informs the system that it also emits a URL semantic type, which the Web Page Viewer receives:

public override void ProcessCarrier(ICarrier carrier)
{
  base.ProcessCarrier(carrier);

  if (carrier.ParentCarrier != null)
  {
    // Additional behavior if this is a web image 
    if (carrier.ParentCarrier.Protocol.DeclTypeName == "WebImage")
    {
      url = carrier.ParentCarrier.Signal.Url.Value;

      if (!String.IsNullOrEmpty(url))
      {
        AddEmitProtocol("Url");
      }
      else
      {
        RemoveEmitProtocol("Url");
      }
    }
  }
}

Windyty Page

Image 8

 

 

 

This is simply a web page viewer receptor with a pre-configured URL:

Image 9

I've docked the view for this below the APOD view:

Image 10

The native .NET WebBrowser control uses an archaic version of Internet Explorer, which apparently can be overridden per application in the registry.  But, wanting to stay away from IE, I've finally incorporated the Chromium web browser. To get this working in .NET, I'm using the excellent CefSharp project. Working with CefSharp is very easy:

protected void ShowPage(string url)
{
  internalUrl = url;
  form.IfNull(() => ReinitializeUI()).Else(() => browser.Load(url));
  Subname = WindowName;
}

protected override void InitializeUI()
{
  base.InitializeUI();
  browser = (ChromiumWebBrowser)mycroParser.ObjectCollection["browser"];
  browser.Load(internalUrl);
}

but be warned, the current implementation of this receptor is incomplete.  I've also found that moving the web page around in the applet UI (docking it to different regions) causes something in the CefSharp code to throw an exception and crash the application.  I haven't been able to isolate this problem. 

It took me a while (and a google that led to the Stack Overflow answer) to figure out why the web page wasn't rendering.  Turns oout I was missing this very important line:

Cef.Initialize();

Cef must be initialized, otherwise it will not render the page!

There are also several external DLL's and other pieces that must be placed into the bin folder, which I've committed to the GitHub repo, so you don't have to deal with that.

Weather Radar

The View:

Image 11

The Applet:

Image 12

Scraping the weather page is described in my article here.

This applet is very similar to the APOD applet.  You'll note the addition of the Interval Timer receptor, which emits a semantic "command" (a semantic type with no native types) that causes the Radar receptor to refresh.

Similarly to the APOD receptor, if you add a Web Page Viewer receptor in the membrane containing the Image Viewer, you can double-click on the image and the system will bring up the full web page.

RSS Feeds

The View:

Image 13

The Applets:

Image 14

Image 15

Here we actually have two applets: the top one parses the RSS feeds persists them to the semantic database, while the bottom one has the receptors involved in displaying the feed and interacting with the database.  Both the feeds and the display have Signal Creator receptors that refresh the data and display at set intervals.

A complete description of this applet can be found in my article here.

Horoscope

The View:

Image 16

The Applet:

Image 17

Here we leverage the Feed Reader receptor again, along with a generic Text Display receptor.  This also illustrates the power of semantic computing.  The feed readers are configured with a site (it's a pretty bad site actually) that provides horoscopes in an RSS format (so, no webpage scraping!):

Image 18

Semantically, the Feed Reader signal involves a lot of types:

Image 19

We're only interested in the description, which ultimately is a Text type with a string Value native type.  The configuration UI for the Text receptor allows us to select a filter, meaning that only signals with this semantic type are displayed:

Image 20

We select the specific semantic type on which to filter. 

If we don't do this, the Text receptor displays every Text sub-type that is emitted, including logger messages and the other feed sub-types, so we would see this instead:

Image 21

This concept of filtering semantic signals will probably be extended to other receptors in the future, as it can help to reduce the need for membranes.  Also, a visual indicator on the design surface for receptors that are filtering signals would be helpful!

The reason we can't use membranes to filter just the "RSSDescription" semantic type, like this:

Image 22

 is that currently the code does not support filtering on a semantic type with no receptors that specifically receive that semantic type -- in other words, the way the code is currently implemented, the "RSSDescription" semantic type doesn't know where to do once it's inside the membrane.  This is a shortcoming that needs to be fixed!

Today's Weather

The View:

Image 23

The Applet:

Image 24

The reason for the exception handler viewer is that frequently, the NOAA web service fails, and we can inspect the exception in the UI (here there is no exception):

Image 25

Conclusion

Image 26

There you have it -- a HOPE "system" that is highly customizable in both visualization and function, creating a rich user experience.  There's lots more to do on this project -- a developer roadmap of sorts is here -- so if you're interested in contributing to this project, drop me a line!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect Interacx
United States United States
Blog: https://marcclifton.wordpress.com/
Home Page: http://www.marcclifton.com
Research: http://www.higherorderprogramming.com/
GitHub: https://github.com/cliftonm

All my life I have been passionate about architecture / software design, as this is the cornerstone to a maintainable and extensible application. As such, I have enjoyed exploring some crazy ideas and discovering that they are not so crazy after all. I also love writing about my ideas and seeing the community response. As a consultant, I've enjoyed working in a wide range of industries such as aerospace, boatyard management, remote sensing, emergency services / data management, and casino operations. I've done a variety of pro-bono work non-profit organizations related to nature conservancy, drug recovery and women's health.

Comments and Discussions

 
-- There are no messages in this forum --