Custom widget: Direction buttons

Tags: #<Tag:0x00007f7459b21d10> #<Tag:0x00007f7459b21bf8>

Hi everyone!

Here’s my new custom widget for you :slight_smile:
Since I’m waiting for a new robot vacuum cleaner to be shipped, I thought I’m gonna create a widget that’ll allow me to control it.

direction-buttons.widget.json (5.0 KB)

This widget contains four directional buttons and one action button on the centre.
Take a look at the gif:

To use it with openHAB you need basically two items - one String item for controlling direction, and second for center button, e.g:

Group Vacuum "Odkurzacz"
    Switch Vacuum_Clean "Odkurzanie" (Vacuum)
    String Vacuum_Direction "Kierunek" (Vacuum) // top right bottom left

You can also adjust the color of the wheel.
Let me know what you think! :slight_smile:

6 Likes

Nice! And totally reusable for other devices with 4-way navigation (the “CLEAN” label might be renamed to “OK” or similar).

This button really looks good. Any chance that the button can change to “Dock” after it has been press to Clean? So that you can send the unit back to it’s charging station?

Hi @kubawolanin,

This is a very cool widget ! Do you think you can do the same with a OK Label or something we can edit ?

I really like to use it for TV control.

Thank you!
The label is customizable already - in Edit menu you can specify “Center button label” which does exactly what you need :slight_smile:

That’s great, It already be a part of my TV Panel, Thanks you !

Hi :slight_smile:
I dont now how to change it, but it will be nice to have 8 buttons, so the new bottons chould be home,back,VolumeUp and down.
Hope that somebody can help :slight_smile:
Br
Jesper

1 Like

Hello!

This widget is really great! I want to use it for my LG-TV. In the preview on my pc-screen it looks good an the buttons are centred in the middle of the widget - but when i want to use it on my iphone it is no longer centered and the size gets too big (when i change the size of the widget, the button even get as bigger as the widget itself).

Do you have an idea, how to fix this?

Thanks a lot,

yours Alex

Hi Alex,
did you ever solve this issue?
I’ve adopted the widget to use as Squeezeplayer Control and I’ve got the same problem.
I found that if i size the box to screen width but little height, the control itself just fits. Nasty workaround at best:

The control itself is working like a charme…only the sizing does not cut it.
Regards,
-OLI

no, i havent solved it, yet. but honestrly i didt try it again.

accually i am thinking of using it in another way, for excample in a modal box, to save so space in the ui, especially on the mobile phone.

Thanks for replying.

@kubawolanin could you maybe help here? The widget is really great, but somehow sizing on smaller displays is a problem :frowning:
Regards,
-OLI

WOW !!! i just love it, i use it in combination with a modified version of Alarm Keypad from lucky mallari to control all my AV for my home cinema.
Great Work, and you made me discover the Glyphicons too !! a lot of possibilities.

1 Like

Hi!
I don’t have it on my current environment, but you may try adding “clearfix” CSS class to the container area?
Also, you may want to play around with the width property of the buttons container.

Cheers

Cool widget - this got me thinking - anyone know if you could use one of these widgets in basic UI via the webpage element? I wouldnt want all the habpanel dressing around the edges just the widget itself

Excellent work, thanks!

Great widget - but sadly I also get the resize issue on a mobile - which means I can’t use it :disappointed_relieved:

If you are still actively developing it - is there an easy fix, or a way to hard specify the dimensions at least?

Also, my css is terrible - how difficult would it be to add 4 buttons in the outside corner white space (around the outside of the current widget)
I like to use this to drive AV gear - so want to add menu / home / back and mute buttons - something vaguely similar to this : https://images.app.goo.gl/57xBPkzHtDg2xy7D6

Have you found help or a workaround? Otherwise perhaps I can help you. I’ve modified this to fit my needs for controlling kodi - with a menu and a back button. Two more shouldn’t be a problem.

Regards,

Hi Florian,

I’d love to see what you’ve done. For now I’ve reverted to a bunch of square buttons, which are functional but don’t look great.
If you’ve added buttons to, that could really help. I bind the buttons to a series of dummy objects which behave differently depending on the input source for my AV recover. This means I have a single remote for about 5 different presser’s(Kodi, plex, satellite, firestick, etc)
Obviously, this means that I need additional buttons like menu.

Please do share…

The current status is not final. I’ve started modifying yesterday and I’m currently not really happy. If you need additional Buttons at the top I can try to create them for you. Also if you didn’t want the control Buttons under the direction buttons.

I’m not allowed to upload the .json file here for importing it to HABPanel because I’m a new user. You have to create any configuration parameter by youself. If you want the .json contact me direct (if this is possible here).

Here is the code (the stop button is currently commented out if you want to use it you have to adjust the width of the buttons in the second row “nav.table .button2 { width: 48%;” to “(nav.table .button2 { width: 23%;)”:

Edit: Now the upload is working Entertainment Control.widget.json (10.4 KB)

<style>
nav.directions {
  --bg-color: transparent;
  --btn-color: {{config.btn_color || '#fff'}};
  --btn-active: #ccc;
  --text-color: #222;
  --size: {{ (ngModel.sizeY > ngModel.sizeX) ? (ngModel.sizeX * 45) : (ngModel.sizeY * 45)  }}px
}

nav.directions {
  width: var(--size);
  height: var(--size);
  background: var(--bg-color);
  border-radius: 50%;
  padding: 20px;
  -webkit-transform: rotate(45deg);
  -moz-transform: rotate(45deg);
  transform: rotate(45deg);
  box-shadow: inset 12px 0 12px -6px var(--btn-color), inset 0 0 0 12px var(--btn-color);
  box-sizing: border-box;
  position: relative;
  margin: 10px auto;
}

nav.directions button {
  background: var(--btn-color);
  color: var(--text-color);
  text-decoration: none;
  outline: none;
  display: block;
  border: none;
  -webkit-transition: .1s background, .2s box-shadow;
}
  
nav.directions button:active {
  background: var(--btn-active);
  box-shadow: inset 2px 4px rgba(0, 0, 0, 0.2);
}

nav.directions .center-button { 
  height: 38%;
  width: 38%;
  position: absolute;
  top: 31%;
  left: 31%;
  border-radius: 50%;
  -webkit-transform: rotate(-45deg);
  -moz-transform: rotate(-45deg);
  transform: rotate(-45deg);
  font-size: 1.250em;
  font-weight: 500;
  text-transform: uppercase;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .33), inset -2px -4px rgba(0, 0, 0, 0.2);
}

nav.directions .center-button:active {
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .33), inset 2px 4px rgba(0, 0, 0, 0.2);
}
  
nav.directions .back-button { 
  height: 30%;
  width: 30%;
  position: absolute;
  top: 100%;
  left: 33%;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .33), inset 0px 0px rgba(0, 0, 0, 0.2);
}

nav.directions .back-button:active {
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .33), inset 2px 4px rgba(0, 0, 0, 0.2);
}

nav.directions .menu-button { 
  height: 30%;
  width: 30%;
  position: absolute;
  top: 33%;
  left: 100%;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .33), inset 0px 0px rgba(0, 0, 0, 0.2);
}

nav.directions .menu-button:active {
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .33), inset 2px 4px rgba(0, 0, 0, 0.2);
}
  
nav.directions .button {
  width: 46%;
  height: 46%;
  margin: 2%;
  position: relative;
  float: left;
}

nav.directions .button::after {
  content: "";
  width: 0;
  position: absolute;
  border-radius: initial;
}

nav.directions button.top {
  border-radius: 100% 0 0 0;
}

nav.directions button.top::after {
  bottom: 0;
  right: 0;
}

nav.directions button.right {
  border-radius: 0 100% 0 0;
}

nav.directions button.right::after {
  bottom: 0;
  left: 0;
}

nav.directions button.left {
  border-radius: 0 0 0 100%;
}

nav.directions button.left::after {
  top: 0;
  right: 0;
}

nav.directions button.bottom {
  border-radius: 0 0 100% 0;
}

nav.directions button.bottom::after {
  top: 0;
  left: 0;
  box-shadow: inset -2px -3px 2px -2px rgba(0, 0, 0, 0.4), -10px -10px 0 10px var(--bg-color);
}
  
nav.directions i {
  -webkit-transform: rotate(-45deg);
  -moz-transform: rotate(-45deg);
  transform: rotate(-45deg);
  position: absolute;
  font-size: calc(var(--size)/10);
  top: 36%;
  left: 39%;
  text-shadow: 1px 1px 4px var(--btn-color), 0px 0px 0px rgba(0, 0, 0, 0.5);
  color: rgba(0, 0, 0, 0.15);
}

nav.directions .button:active i {
    color: var(--text-color);
    text-shadow: none;
}

nav.directions .top i {
  top: 35%;
  left: 41%;
}

nav.directions .left i {
  top: 41%;
  left: 35%;
}

nav.directions .right i {
  top: 35%;
  left: 41%;
}

nav.directions .bottom i {
  top: 39%;
  left: 42%;
}
  
nav.table {
  --bg-color: transparent;
  --btn-color: {{config.btn_color || '#fff'}};
  --btn-active: #ccc;
  --text-color: #222;
  --size: {{ (ngModel.sizeY > ngModel.sizeX> ngModel.sizeX) ? (ngModel.sizeX * 100) : (ngModel.sizeY * 100)  }}px
}

nav.table {
  width: var(--size);
  height: var(--size);
  background: var(--bg-color);
  border-radius: 0%;
  padding: 20px;
  box-sizing: border-box;
  position: relative;
  margin: 50px auto;
}
  
nav.table button {
  background: var(--btn-color);
  color: var(--text-color);
  text-decoration: none;
  outline: none;
  display: block;
  border: none;
  -webkit-transition: .1s background, .2s box-shadow;
}
  
nav.table button:active {
  background: var(--btn-active);
  box-shadow: inset 2px 4px rgba(0, 0, 0, 0.2);
}

nav.table .button {
  width: 23%;
  height: 15%;
  margin: 1%;
  position: relative;
  float: left;
}
  
nav.table .button::after {
  content: "";
  width: 0;
  position: absolute;
  border-radius: initial;
}

nav.table button2 {
  background: var(--btn-color);
  color: var(--text-color);
  text-decoration: none;
  outline: none;
  display: block;
  border: none;
  -webkit-transition: .1s background, .2s box-shadow;
}
  
nav.table button2:active {
  background: var(--btn-active);
  box-shadow: inset 2px 4px rgba(0, 0, 0, 0.2);
}

nav.table .button2 {
  width: 48%;
  height: 15%;
  margin: 1%;
  position: relative;
  float: left;
}
  
nav.table .button2::after {
  content: "";
  width: 0;
  position: absolute;
  border-radius: initial;
}  
  
nav.table i {
  position: absolute;
  font-size: calc(var(--size)/30);
  top: 36%;
  left: 39%;
  text-shadow: 1px 1px 4px var(--btn-color), 0px 0px 0px rgba(0, 0, 0, 0.5);
  color: rgba(0, 0, 0, 0.15);
}

nav.table .button:active i {
    color: var(--text-color);
    text-shadow: none;
}
  
</style>
<nav class="directions">
	<button class="button top" ng-click="sendCmd(config.direction_button, config.up_command)"><i class="glyphicon glyphicon-chevron-up"></i></button>
	<button class="button right" ng-click="sendCmd(config.direction_button, config.right_command)"><i class="glyphicon glyphicon-chevron-right"></i></button>
	<button class="button left" ng-click="sendCmd(config.direction_button, config.left_command)"><i class="glyphicon glyphicon-chevron-left"></i></button>
	<button class="button bottom" ng-click="sendCmd(config.direction_button, config.down_command)"><i class="glyphicon glyphicon-chevron-down"></i></button>
	<button class="center-button" ng-click="sendCmd(config.center_button, config.center_command)">{{config.center_label}}</button>
  <button class="back-button" ng-click="sendCmd(config.back_button, config.back_command)"> <i class="glyphicon glyphicon-arrow-left"></i></button>
  <button class="menu-button" ng-click="sendCmd(config.menu_button, config.menu_command)"> <i class="glyphicon glyphicon-menu-hamburger"></i></button>
</nav>

<nav class="table">
	<button class="button" ng-click="sendCmd(config.playback_button, config.stepbackward_command)"> <i class="glyphicon glyphicon-step-backward"></i></button>
  <button class="button" ng-click="sendCmd(config.playback_button, config.backward_command)"> <i class="glyphicon glyphicon-backward"></i></button>
  <button class="button" ng-click="sendCmd(config.playback_button, config.forward_command)"> <i class="glyphicon glyphicon-forward"></i></button>
  <button class="button" ng-click="sendCmd(config.playback_button, config.stepforward_command)"> <i class="glyphicon glyphicon-step-forward"></i></button>
<!--<button class="button" ng-click="sendCmd(config.playback_button, config.stop_command)"> <i class="glyphicon glyphicon-stop"></i></button> -->
  <button class="button2" ng-click="sendCmd(config.playback_button, config.pause_command)"> <i class="glyphicon glyphicon-pause"></i></button>
  <button class="button2" ng-click="sendCmd(config.playback_button, config.play_command)"> <i class="glyphicon glyphicon-play"></i></button>
</nav>

Regards from Germany

Florian - that is looking great.
Have you made more progress?

Have you tried dropping buttons on the corners outsode of the remote - like on this remote: https://apps.apple.com/gb/app/official-kodi-remote/id52048036
?

Either way, I am going to have to give your json examplke a test :slight_smile: